It is common practice to publish a new site as soon as functional testing is complete. However, default configurations are designed for “usability,” not “security”—using default backend paths, overly permissive directory permissions, and lacking backups constitute risks the moment you go live.
The following checklist is organized by tasks that can be completed before launch, focusing on low-cost, high-impact measures.
1. Accounts and Access Entry Points
| Item | Requirement | Command/Action |
|---|---|---|
| SSH | Disable root login; use key-based authentication | PermitRootLogin no |
| SSH | Disable password login | Verify key access first, then change |
| Server | Use standard user + sudo | adduser |
| Backend | Do not use default admin username | Change to a non-admin username |
| Backend | Strong password + login restrictions | Limit attempt counts |
| Database | Do not use root for application connections | Create dedicated accounts with minimal privileges |
# Verify SSH configuration
grep -E 'PermitRootLogin|PasswordAuthentication' /etc/ssh/sshd_config
# Verify database is not using root for application connection
grep -iE 'DB_USER|DB_PASSWORD' /var/www/html/wp-config.php
The “default admin username” item is most easily overlooked, but it offers the lowest-cost protection—automated scanners target these default names first.
2. Port Exposure and Service Surface
# Check which ports are exposed externally
ss -lntp
# Scan yourself from an external network (use another machine)
nmap -Pn ServerPublicIP
# Verify these should NOT be open to the public internet
ss -lntp | grep -E '3306|6379|27017|9200'
| Port | Service | Should be Open to Public? |
|---|---|---|
| 22 | SSH | Yes, but restrict source IPs |
| 80/443 | Web | Yes |
| 3306 | MySQL | No |
| 6379 | Redis | No |
| 27017 | MongoDB | No |
| 8888 | CPanel/Dashboard | Restrict source IPs or change port |
# Firewall allows only necessary ports
firewall-cmd --list-all
# Cloud security groups must also be confirmed in the console
3. File and Directory Permissions
# Directory 755, File 644 is a common baseline
find /var/www/html -type d -exec chmod 755 {} ;
find /var/www/html -type f -exec chmod 644 {} ;
# Tighten config file permissions
chmod 600 /var/www/html/wp-config.php
# Check for 777 (overly permissive) permissions
find /var/www/html -perm -0777 -print
777 permissions are the most common form of over-authorization. They imply that any user can write, including malicious processes created after a compromise.
4. Sensitive Files Must Be Inaccessible
# Deny access to these paths
location ~ /. {
deny all;
}
location ~* .(env|git|svn|sql|bak|log)$ {
deny all;
}
# Verify (should return 403)
curl -I https://example.com/.env
curl -I https://example.com/.git/config
Do not rely on “file does not exist” for security. Explicit denial is certain.
5. Disable Directory Listing
autoindex off;
# Verify: Access a directory without an index file
curl -I https://example.com/wp-content/uploads/
# Should NOT return a directory listing
6. Backups and Rollback
You must confirm these two things before launch; otherwise, if issues arise post-launch, there is no way back:
# ① Have rollback-capable data
wp db export backup-before-launch.sql # WordPress
# Or mysqldump
# ② Backup off-site (not on the same machine)
rsync -avz /data/backup/ root@BackupServer:/data/backup/
7. HTTPS and Monitoring
# HTTPS enabled and chain complete
openssl s_client -connect example.com:443 -servername example.com
-verify_return_error </dev/null 2>/dev/null | grep -i 'verify return'
# HTTP auto-redirect to HTTPS
curl -I http://example.com/ | grep -i location
# Monitoring (at minimum):
# - Site availability
# - Disk space
# - Certificate expiration
Complete Checklist
| Category | Check Item |
|---|---|
| Accounts | SSH disable root/password; Backend non-default username; DB dedicated account |
| Ports | Only necessary ports open; 3306/6379 not public; Security group confirmed |
| Permissions | Dirs 755, Files 644; Configs 600; No 777 |
| Sensitive Files | .env / .git etc. access denied |
| Dir Listing | Disabled |
| Backups | Rollback data available, backed up off-site |
| HTTPS | Enabled, complete chain, HTTP redirect |
| Monitoring | Availability, disk, cert expiry |
| Updates | Core/plugins/system updated to recent versions |
Decision Tree
Pre-launch Hardening
├─ Highest Priority (Lowest Cost, Highest Return)
│ ├─ Backend uses non-default username
│ ├─ 3306/6379 not public
│ ├─ No 777 permissions
│ └─ .env/.git access denied
├─ Mandatory Fallback
│ ├─ Pre-launch backup (off-site)
│ └─ Confirm rollback capability
└─ Post-launch Continuous
├─ Monitoring (availability/disk/cert)
└─ Regular updates
Scenario Simulation: Dark Links Injected on Day One
Symptom: A new site goes live for less than a day, gets flagged by search engines as abnormal,
and unexplained external links appear on pages. Functional tests passed pre-launch; no one considered security.
- First, identify the intrusion path → Check for abnormal backend operations or new files,
determine if via management entry or service vulnerability. - Review pre-launch configurations → Backend used default address, weak passwords,
remote login port open to all, password auth not disabled. - Containment: Reduce exposure surface → Restrict backend access source/frequency, disable remote password login,
revert to key-based auth. - Clean and trace residues → Check cron jobs and new accounts,
order: disconnect mechanism first, then clean files. - Fulfill pre-launch requirements → Update to latest patches, tighten dir permissions,
disable script execution in upload dirs, enable backups and alerts. - Verify and archive → Confirm open ports and permissions item by item, solidify this check into a launch checklist.
# See what is open
ss -lntp
# Check for intrusions
last -10
awk -F: '$3>=1000 && $7 !~ /nologin|false/ {print $1,$3,$7}' /etc/passwd
crontab -l -u root
# Dir permissions and executability
find /WebsiteDir -type d -perm -o+w | head
ls -ld /WebsiteDir/wp-content/uploads 2>/dev/null
# Disable script execution in upload dir (Web layer)
# nginx: location ~* ^/wp-content/uploads/.*.php$ { deny all; }
Root Cause: Only functional availability was verified at launch, without basic hardening.
Services exposed to the public internet are typically targeted by automated scans much faster than expected;
default addresses and weak passwords won’t survive the first day.
Two key takeaways:
- “Tested and working” and “Ready for launch” are two completely different standards.
The latter includes mandatory pre-launch actions like default addresses, weak passwords, open ports, and dir permissions. - Hardening order: reduce exposure surface first, then clean residues.
Cleaning without blocking entry points is like sweeping while wiping; it never gets clean.
8 Common Pitfalls
- Using “admin” for backend: Lowest cost change, highest return.
- 3306/6379 open to public: Primary intrusion vectors.
- 777 permissions for convenience: Equivalent to abandoning permission control.
- Configuring firewall but forgetting security group: Two independent layers.
- Assuming “file doesn’t exist” means secure: Should explicitly deny access.
- No backup before launch: No fallback if issues arise.
- Backup on same machine: Lost together if machine fails.
- No monitoring post-launch: Can only wait for user feedback when issues occur.
Real Customer Feedback (From Cloud Market Reviews and Consultations for Similar Products)
The following excerpts are taken from real buyer reviews and consultations for similar O&M services on Alibaba Cloud / Tencent Cloud / Huawei Cloud marketplaces (providers include our store and peers, provided for reference only, not fictional tickets):
1****8 Rating: 5.0 Date: 2019-10-29 22:35 Good 1
1****1 Rating: 5.0 Date: 2020-06-18 11:50 1****1 Rating: 5.0 Date: 2020-04-26 18:46 1****1 Rating: 5.0 Date: 2020-04-26 18:45 1****1 Rating: 5.0 Date: 2020-04-26 18:45 1****1 Rating: 5.0 Date: 2020-04-26 18:45 1****1 Rating: 5.0 Date: 2020-04-26 18:44 He****She Rating: 5.0 Date: 2019-09-26 09:47