A one-command, production-hardened Linux server provisioning system. Installs Docker, Git, configures the firewall, hardens SSH, creates users, and deploys a containerised web application — all from a single script.
| Feature | Details |
|---|---|
| 🔄 System Update | Upgrades packages before any installation |
| 🐳 Docker Install | Auto-detects OS, uses official Docker repositories |
| 🔧 Git Install | Installs Git via native package manager |
| 🔥 Firewall Config | ufw on Debian/Ubuntu · firewalld on RHEL |
| 🔒 SSH Hardening | Disables root login, password auth, X11 forwarding |
| 👤 User Creation | Creates non-root user, added to sudo/wheel + docker groups |
| 🌐 App Deployment | Deploys a Docker container with real health-check polling |
| 📝 Full Logging | Timestamped output in logs/deploy.log (auto-rotated at 5MB) |
| ♻️ Idempotent | Safe to re-run — skips already-completed steps |
| ⛔ Fail-fast | Stops immediately on failure with cleanup trap |
| 🧪 Dry-run mode | --dry-run shows what would happen without making changes |
| 🛡️ Hardened | Pinned image tags, config validation, sudo pre-flight, disk check |
Debian-based — Ubuntu 20.04 / 22.04 / 24.04, Debian 11 / 12, Raspberry Pi OS
RHEL-based — CentOS 8+, RHEL 8/9, Fedora 38+, Rocky Linux 8/9, AlmaLinux 8/9
server_deployment_toolkit/
├── .github/workflows/
│ └── lint.yml # ShellCheck CI on every push
├── configs/
│ ├── env.config # Your settings (gitignored)
│ ├── env.config.example # Template (committed to git)
│ └── nginx.conf # Nginx reverse proxy config (mounted into container)
├── logs/
│ └── deploy.log # Auto-generated, auto-rotated
├── scripts/
│ ├── update_system.sh # Step 1
│ ├── install_docker_debian.sh # Step 4a
│ ├── install_docker_red_hat.sh # Step 4b
│ ├── install_git.sh # Step 5
│ ├── configure_firewall.sh # Step 2 (+ SSH hardening)
│ ├── create_users.sh # Step 3
│ └── deploy_app.sh # Step 6
├── deploy_server.sh # Master orchestrator
├── .gitignore
└── README.md
cp configs/env.config.example configs/env.config
nano configs/env.configKey settings:
APP_NAME="nginx-app"
APP_IMAGE="nginx:1.27.4" # Always pin a specific version — never use :latest
APP_PORT=80
USERNAME="devuser"Security:
configs/env.configis gitignored. Never commit it. Add secrets only there.
# Clone the repository
git clone https://github.com/yourusername/server-deployment-toolkit.git
cd server-deployment-toolkit
# Configure
cp configs/env.config.example configs/env.config
nano configs/env.config
# Make executable
chmod +x deploy_server.sh
# Dry-run first (see what would happen without making changes)
sudo ./deploy_server.sh --dry-run
# Run the full deployment
sudo ./deploy_server.sh# Follow live deployment
tail -f logs/deploy.log
# Search for errors
grep "ERROR\|WARNING" logs/deploy.log
# Re-run a single step
bash scripts/deploy_app.sh| Practice | Where |
|---|---|
| SSH rate limiting (6 attempts/30s) | configure_firewall.sh |
| Root login + password auth disabled | configure_firewall.sh |
| Pinned Docker image tags | env.config |
| Config file validated before sourcing | deploy_server.sh |
| Log file permissions: 640 | deploy_server.sh |
| nginx security headers | nginx.conf |
| Secrets gitignored | .gitignore |
| ShellCheck CI | .github/workflows/lint.yml |
MIT — free to use, modify, and distribute.