harden-vps
Harden a production Linux VPS for your application across three layers — application (systemd hardening, monitoring alerts, backup automation), Ubuntu OS (UFW…
Skill by danielvm-git
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/danielvm-git-harden-vps-de038b
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: backend, security
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions: not checked yet.
What's inside
- Skill name
harden-vps- Description
- Harden a production Linux VPS for your application across three layers — application (systemd hardening, monitoring alerts, backup automation), Ubuntu OS (UFW firewall, fail2ban SSH, unattended-upgrades, SSH hardening), and VPS provider (health checks, daily backups, monthly snapshots). Use when the user wants to secure a production server, harden a VPS, audit server security, or mentions production hardening, VPS security, or harden the server.
- License
- MIT
- Instructions
- 287 lines in SKILL.md · view on GitHub
Before installing
- Instructions call the network
Files (1)
- SKILL.md
SKILL.md (first lines)
# Harden VPS
Three-layer production hardening for a self-hosted app on any VPS. Each layer independently verifiable. Apply OS first (firewall blocks attacks immediately), then your application (alerts + backups), then your VPS provider (snapshots). See [REFERENCE.md](REFERENCE.md) for full script bodies, systemd unit template, and gotchas.
## Quick start
SSH as root into the VPS. Find credentials in the your VPS provider Customer Control Panel.
> **HARD GATE** — Run `ufw status` first. No firewall = layer 1 takes priority over everything.
## Layer 1 — Ubuntu OS
```bash
# UFW
ufw default deny incoming && ufw default allow outgoing
ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable
# → verify: ufw status | grep -q active
# fail2ban
apt install -y fail2ban
# Configure /etc/fail2ban/jail.local: sshd, maxretry=3, bantime=3600, findtime=600
systemctl restart fail2ban
# → verify: fail2ban-client status sshd
# unattended-upgrades
apt install -y unattended-upgrades && dpkg-reconfigure -plow unattended-upgrades
# → verify: systemctl is-active unattended-upgrades | grep -q active
# SSH: PermitRootLogin no, PasswordAuthentication no, PubkeyAuthentication yes
# → verify: sshd -T | grep -E 'permitrootlogin no|passwordauthentication no'
# Deploy healthcheck.sh → /opt/your-app/scripts/healthcheck.sh
# Crontab: */5 * * * * /opt/your-app/scripts/healthcheck.sh
```
## Layer 2 — applicationlication
```bash
# systemd: User=your-app, NoNewPrivileges=yes, ProtectSystem=full,
# ProtectKernelTunables=yes, ProtectKernelModules=yes,
# ProtectControlGroups=yes, RestrictAddressFamilies=AF_INET AF_INET6,
# RestrictRealtime=yes, PrivateTmp=yes, LimitNOFILE=65536
# → verify: systemctl show your-app -p NoNewPrivileges -p ProtectSystem -p User
# Alerts (your application requires auth; insert via SQLite)
sqlite3 /opt/your-app/data/your-app.db "
INSERT INTO monitoring_alerts (id,name,metric,threshold,operator,enabled,duration_seconds)
VALUES ('a1','Disk >80%','disk_used_percent',80,'gt',1,300);
INSERT INTO monitoring_alerts (id,name,metric,threshold,operator,enabled,duration_seconds)
VALUES ('a2','CPU >90%','cpu_percent',90,'gt',1,60);
INSERT INTO monitoring_alerts (id,name,metric,threshold,operator,enabled,duration_seconds)
VALUES ('a3','RAM >85%','mem_used_percent',85,'gt',1,120);
"
systemctl restart your-app
# Backup crontab (root):
# 0 2 * * * cp /opt/your-app/data/your-app.db /backup/your-app-$(date +\%Y\%m\%d).db
# 0 3 * * * find /backup/ -name "your-app-*.db" -mtime +90 -delete
```
## Layer 3 — VPS provider
```bash
# cntb CLI
curl -sL "$(curl -sL https://api.github.com/repos/contabo/cntb/releases/latest \
| grep browser_download_url.*linux_amd64.tar.gz | head -1 | cut -d'"' -f4)" \
| tar xz -C /usr/local/bin
# Snapshot script → /opt/your-app/scripts/contabo-snapshot.sh (reads from /opt/your-app/.env)
# Credentials as env vars in /opt/your-app/.env (deployed by GitHub Actions):
# CONTABO_CLIENT_ID, CONTABO_CLIENT_SECRET, CONTABO_API_USER, CONTABO_API_PASSWORD
# Crontab: 0 4 1 * * /opt/your-app/scripts/contabo-snapshot.sh
# > HARD GATE — Snapshot cron silently fails until env vars are set in .env.
# Credentials source: your VPS provider Customer Panel → API Details.
# Local dev: add to .envrc. Production: GitHub Secrets → deploy → /opt/your-app/.env
```
## CRITICAL GOTCHAS
1. **Shell escaping in Orca terminals:** `$VAR`, `$(…)`, and `%` get eaten by the local shell. Always use base64: `echo '<base64>' | base64 -d > script.sh`
2. **Crontab `%`:** cron interprets `%` as newline. Escape as `\%` in `$(date +\%Y\%m\%d)`
3. **fail2ban exit 255:** means a jail references a missing log file. Remove the broken jail, restart.
4. **your application alerts need auth:** POST to `/api/monitoring/alerts` requires Bearer token. Workaround: insert directly into SQLite, then restart your application.
## Verify all 8 gates
```bash
ufw status|grep -q active||echo FAIL:ufw
fail2ban-client status sshd>/dev/null 2>&1||echo FAIL:fail2ban
systemctl is-active unattended-upgrades|grep -q active||echo FAIL:unattended
sshd -T|grep -q 'permitrootlogin no'||echo FAIL:sshd
systemctl show your-app -p NoNewPrivileges|grep -q yes||echo FAIL:systemd
systemctl is-active your-app|grep -q active||echo FAIL:your-app
sqlite3 /opt/your-app/data/your-app.db "SELECT count(*) FROM monitoring_alerts"|grep -q 3||echo FAIL:alerts
crontab -l|grep -q healthcheck&&crontab -l|grep -q your-app.db&&crontab -l|grep -q contabo-snapshot||echo FAIL:crontab
echo ALL 8 GATES PASSED
```
→ verify: # requires VPS SSH — run the 8-gate one-liner on the VPS manually
---
# Harden VPS — Reference
## Health check script
Deploy to `/opt/your-app/scripts/healthcheck.sh`:
```bash
#!/bin/bash
LOG=/var/log/your-app/health.log
mkdir -p /var/log/your-app
DISK=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
RAM=$(free | awk '/Mem:/ {printf "%.0f", $3/$2*100}')
NOW=$(date -Iseconds)
[ "$DISK" -gt 85 ] && echo "$NOW ALERT: Disk ${DISK}%" >> "$LOG"
[ "$RAM" -gt 90 ] && echo "$NOW ALERT: RAM ${RAM}%" >> "$LOG"
systemctl is-active --quiet your-app || { echo "$NOW ALERT: your application DOWN" >> "$LOG"; systemctl restart your-app; }From danielvm-git/bigpowers, MIT.
More from danielvm-git/bigpowers
- 0.556score
diagnose-root
danielvm-git
Run 4-phase root cause analysis — reproduce, isolate, hypothesize, verify.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
diagnose-stall
danielvm-git
Diagnose why agent orchestration stopped producing progress — silent stalls in /loop, dispatch-agents, or execute-plan.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
align-grid
danielvm-git
Build editorial/magazine/report webpages on a GENUINE Müller-Brockmann modular grid (International Typographic Style) — not a decorative one.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
assess-impact
danielvm-git
Analyze the blast radius of a proposed change before any code is written.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
audit-code
danielvm-git
Self-review checklist for the coding agent to run before dispatching a reviewer.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
compose-workflow
danielvm-git
Chain multiple bigpowers skills into a custom workflow recipe saved in specs/.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
context7-mcp
danielvm-git
Fetch current library docs via Context7 MCP instead of training data.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
audit-plan
danielvm-git
Evaluate an incoming project plan against bigpowers principles and conventions, surface gaps, and produce a READY/NOT READY verdict before engagement begins.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
deepen-architecture
danielvm-git
Find deepening opportunities in a codebase, informed by the domain language in specs/tech-architecture/tech-stack.md and the decisions in specs/adr/.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
define-language
danielvm-git
Extract a DDD-style ubiquitous language glossary from the current conversation, flagging ambiguities and proposing canonical terms.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
change-request
danielvm-git
Add a new requirement or reorder epics by WSJF against specs/release-plan.yaml and epic capsule directories.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
dispatch-agents
danielvm-git
Dispatch multiple subagents in parallel on independent tasks.
SkillBFreshness: B★ 271Claude Code +9
Signals
- Stars
- 271
- Forks
- 24
- Open issues
- 11
- Last commit (this folder)
- Jul 26, 2026 (3 months ago)
- Last release
- Sep 21, 2026 (1 month ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/danielvm-git/bigpowers
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
Same skill elsewhere
Copies of this SKILL.md published by others; search shows only one of them.
- 0.556score
harden-vps
danielvm-git
Harden a production Linux VPS for your application across three layers — application (systemd hardening, monitoring alerts, backup automation), Ubuntu OS (UFW…
SkillBFreshness: B★ 271Claude Code +9 - 0.290score
harden-vps
danielvm-git
Harden a production Linux VPS for your application across three layers — application (systemd hardening, monitoring alerts, backup automation), Ubuntu OS (UFW…
SkillBFreshness: B★ 271Claude Code +9 - 0.290score
harden-vps
danielvm-git
Harden a production Linux VPS for your application across three layers — application (systemd hardening, monitoring alerts, backup automation), Ubuntu OS (UFW…
SkillBFreshness: B★ 271Claude Code +9
More from danielvm-git
- 0.556score
align-grid
danielvm-git
Build editorial/magazine/report webpages on a GENUINE Müller-Brockmann modular grid (International Typographic Style) — not a decorative one.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
audit-code
danielvm-git
Self-review checklist for the coding agent to run before dispatching a reviewer.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
audit-plan
danielvm-git
Evaluate an incoming project plan against bigpowers principles and conventions, surface gaps, and produce a READY/NOT READY verdict before engagement begins.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
assess-impact
danielvm-git
Analyze the blast radius of a proposed change before any code is written.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
change-request
danielvm-git
Add a new requirement or reorder epics by WSJF against specs/release-plan.yaml and epic capsule directories.
SkillBFreshness: B★ 271Claude Code +9 - 0.556score
compose-workflow
danielvm-git
Chain multiple bigpowers skills into a custom workflow recipe saved in specs/.
SkillBFreshness: B★ 271Claude Code +9
Cite this page
harden-vps skill. Agent Mart. https://agentmart.dev/skills/danielvm-git-harden-vps-de038b (last updated 2026-10-24)