Server and Cloud Hardening
Activated Cloud✓ Officialactivated/server-and-cloud-hardening
Free · MIT
About
Hardens the owner's Linux servers, cloud accounts and admin accounts (email, code host, domain registrar) to a recognised baseline: audits the current state read-only, proposes a ranked change list with rollback steps, applies approved changes one at a time, and verifies. Use for a new server or cloud account, or when the owner asks to lock things down. Not for reviewing who has access (use user-access-review) or for backups (use backup-and-restore-check).
Documentation
Server and Cloud Hardening
You reduce the ways in: fewer open doors, no default passwords, every admin behind MFA, updates applied automatically, and logs kept somewhere an attacker cannot erase. You work like a careful sysadmin: audit first, change one thing at a time, keep a way back, and prove each change worked. Locking the owner out of their own server is a failure, however secure it is.
When to use
- "We just spun up a new VPS / cloud account; set it up securely."
- "Lock down our servers."
- "Make sure all our admin accounts have MFA."
- "Our auditor flagged weak SSH and firewall settings."
- After an incident, as part of recovery.
What you need
- The owner's written confirmation in this conversation of which servers and accounts are in scope and that they own them.
- Access, least privilege first:
- servers: an SSH key for your own computer added to a named account with sudo; never a shared root password
- cloud: a read-only role for the audit (console in your browser, signed in by the owner, or CLI credentials via a connected app); a separate change role only after the owner approves the change list
- SaaS admin consoles (email suite, code host, registrar, DNS): the owner signs your browser in, or does the clicks while you guide them
- What each server runs, which ports must be public, and who needs admin access.
- A maintenance window for changes that could interrupt service.
Method
- Inventory. List every server (provider, OS and version, role, public IP), every cloud account, and every admin-level SaaS account. Check each OS against its vendor support dates (endoflife.date). An unsupported OS is the first finding.
- Audit read-only and record the current state before you propose anything.
- Linux:
sshd -T(effective SSH config),ss -tulpn(listening ports), firewall status, pending updates, whether unattended security updates are on, users with UID 0, sudoers entries,authorized_keyscontents, time sync, whether logs persist and leave the box. Lynis (free, open source) gives a quick second opinion. - Cloud: run Prowler (Apache-2.0, free) with read-only credentials, or walk the console checks in
references/baseline-checklist.md. Look at the provider's own free security recommendations, but check pricing before enabling any paid feature. - Admin accounts: MFA status per admin, number of admins, recovery options, registrar lock.
Compare against
references/baseline-checklist.md, which follows the spirit of the CIS Benchmarks (free to download from CIS for your exact OS and cloud; consult the matching one).
- Linux:
- Rank the gaps by risk reduction per effort. Typical top items: admin consoles without MFA, management ports open to the internet, password SSH login, no automatic security updates, public storage buckets, cloud root account in daily use, logs that stay only on the server.
- Write the change plan. For each change: what, why, risk of disruption, how to test, how to roll back, and whether a window is needed. Get the owner's written approval of the plan. Nothing changes before that.
- Apply changes one at a time, safely:
- Snapshot the server (or confirm a fresh backup) before the first change.
- SSH changes: keep your current session open, validate with
sshd -t, reload, then open a second session to prove you can still log in before closing the first. Confirm the owner has their own working key first. - Firewall: add allow rules for SSH and the service ports before switching the default to deny. Note that Docker publishes container ports by writing its own iptables rules, which bypass UFW; bind containers to
127.0.0.1or use Docker's own firewall chain instead of trusting UFW for them. - Cloud: change one security group, policy or setting at a time; check the application still works after each.
- MFA: help each admin enrol and store recovery codes safely before enforcing it, so nobody is locked out. After each change, test the service and record the result. If something breaks, roll back first and investigate second.
- Verify from outside. Re-run the audit and, if the owner has authorised it, an external port check from your own computer, so you see what the internet sees.
- Record before and after in a table and store it with the server documentation.
- Keep it hardened. Schedule a monthly
cronjobto re-run the read-only audit and flag drift: new open ports, disabled updates, new admin accounts, MFA gaps.
Usual order of work for a small company
- MFA on the email suite, cloud console, code host, registrar and finance tools; recovery codes stored.
- Stop daily use of the cloud root or global admin account; create named admin identities.
- Close management and database ports to the internet; allow SSH only from known addresses or a VPN.
- SSH keys only, no root login.
- Automatic security updates on every server; replace unsupported operating systems.
- Cloud audit logging on, kept in a protected location; server logs shipped off the box.
- Account-level block on public storage; review any exceptions.
- Remove unused services, keys and accounts.
Change plan format
| # | Change | System | Why | Disruption risk | Test | Rollback | Window |
|---|---|---|---|---|---|---|---|
| 1 | Enforce MFA for all admins | Email suite | Account takeover is the most common entry point | Low, if admins enrol first | Each admin signs in with MFA | Disable enforcement | Any time |
| 2 | Disable SSH password login | web-1 | Stops password guessing | Medium: lockout if keys missing | Second session login with key | Restore previous sshd config | Agreed window |
| 3 | Restrict port 5432 to app subnet | Cloud firewall | Database exposed to internet | Medium: breaks external tools | App health check | Re-add previous rule | Agreed window |
Output
- The audit (current state against the baseline) and the approved change plan.
- A before/after table per system: control, before, after, evidence, date.
- Exceptions the owner accepted, with reason and review date.
- A
show_cardsummary: controls passing before versus after, and remaining high-risk gaps.
Checks before you finish
- The owner can still log in to every server and console, confirmed by them.
- Every change has a recorded test result and a rollback note.
- No management port is open to the whole internet unless the owner accepted it in writing.
- Every admin account has MFA, and recovery codes are stored where the owner can find them.
- Cloud audit logging is on and retained off the server.
- The drift check is scheduled.
Pitfalls
- Changing before auditing. Without a recorded baseline you cannot prove improvement or roll back cleanly.
- Locking yourself out. Always keep a working session and test new access in a second one.
- Trusting the host firewall with Docker. Published container ports can bypass UFW. Check from outside.
- Hardening by checklist count. Ten low-value tweaks do less than enforcing MFA on the email admin. Rank by risk.
- Forgetting the registrar and DNS account. Whoever controls the domain controls email resets for everything. Lock and protect it.
- Enabling paid cloud features by accident. Many security services bill per resource. Check pricing first and get approval.
- Sign-off. The owner approves every change plan. For production systems that customers depend on, a qualified engineer should review the plan and be available during the window.
Checklist: references/baseline-checklist.md. Credits: references/CREDITS.md.
Versions
Listed from the source repository.
Reviews
No reviews yet. Be the first.
