Converts a empty Ubuntu System into a container host.
Sets up a preconfigured container-host running Kubernetes or Docker Swarm (selectable).
Sets up security measures and automated certificate renewing.
And more.
Features: Docker CE • k3s/Swarm (User Choice) • SSHGuard • Fail2Ban • Certbot • UFW Firewall • SSH Hardening • Admin User Security • Unattended Upgrades
This script should be run on a fresh Ubuntu server installation (20.04 or newer), it sets up a secure, production-ready container host with the following features:
-
Container platform: k3s (default) or Docker CE + Swarm
-
Nginx as a reverse proxy / container router
-
SSH hardening (disables root login, enforces key auth, custom port)
-
Brute-force protection: SSHGuard and Fail2Ban
-
UFW firewall with minimal open ports
-
Certbot (optional) for automatic HTTPS via Nginx
-
Unattended upgrades and basic system hardening
At the end of the run a detailed report is generated with access details, custom ports, and service statuses.
# Download and make executable
chmod +x ubuntu-server-setup.sh
# Interactive setup (recommended)
sudo ./ubuntu-server-setup.sh
# Non-interactive setup with admin user
sudo ./ubuntu-server-setup.sh --yes --admin-user containeruser --admin-password "mypassword" --admin-key "ssh-ed25519 AAAA..."
# Preview what would be installed
sudo ./ubuntu-server-setup.sh --dry-run-
-y, --yes: Auto-confirm prompts (requires--admin-user,--admin-password, and--admin-key). -
-n, --dry-run: Show planned actions without applying changes. -
-r, --report-only: Generate the saved installation report. -
--admin-user <username>: Non-root admin account to create. -
--admin-password <password>: Password for the admin user (required for sudo). -
--admin-key <ssh-public-key>: SSH public key for the admin user. -
--recovery-key <ssh-public-key>: Optional recovery admin key.
-
The script DISABLES direct root SSH login and also disables password authentication. You MUST ensure an admin user with a working SSH public key AND password is configured before the final SSH hardening step or you will be locked out.
-
In automatic mode (
--yes)--admin-user,--admin-password, and--admin-keyare required. -
Keep the generated report (saved under
/root/server-setup-*.report) — it contains custom ports and access details.
-
Script:
ubuntu-server-setup.sh -
Saved port configuration:
/etc/server-ports.conf(SSH and k3s API ports) -
Log file:
/var/log/ubuntu-server-setup.log -
Generated reports:
/root/server-setup-<timestamp>.report -
Error/debug artifacts (on failure):
.ubuntu-server-setup.errorand.ubuntu-server-setup.debugin the script directory
-
Docker CE - Latest Docker Community Edition
-
Automatic daemon configuration
-
User group management
-
Service auto-start configuration
-
k3s - Lightweight Kubernetes with containerd runtime
-
Docker Swarm - Docker CE with Swarm orchestration
-
Security Hardening:
-
Pod Security Admission (PSA) for k3s (replaces deprecated PodSecurityPolicy)
-
Network Security Policies
-
Admission Controllers (NodeRestriction, ResourceQuota)
-
RBAC enforcement
-
Encrypted secrets at rest
-
-
Nginx - High-performance web server
-
Container routing and load balancing
-
Reverse proxy for container services
-
SSL/TLS termination for Certbot
-
Ready for container orchestration
-
Fail2Ban - Advanced intrusion prevention system
-
SSH brute-force protection
-
HTTP/HTTPS attack mitigation
-
Custom jail configurations
-
Email notifications
-
-
SSHGuard - Real-time SSH attack detection
-
UFW firewall integration
-
Automatic IP blocking
-
Whitelist support
-
-
Certbot - Let’s Encrypt SSL certificates
-
Automatic certificate renewal via Nginx plugin
-
Multiple domain support
-
Automatic Nginx HTTPS configuration
-
Note: Domain must resolve to server IP and port 80 must be accessible
-
Custom port assignment for all services
-
Non-standard ports to reduce attack surface
-
Configurable port ranges
-
Automatic conflict detection
-
Key-only authentication (password auth disabled)
-
Root SSH login DISABLED (PermitRootLogin no)
-
Non-root admin user with sudo access required
-
Optional recovery admin account for failsafe access
-
Custom SSH port assignment
-
Protocol version enforcement
-
Connection rate limiting
-
Minimal attack surface (only required ports open)
-
Service-specific rule sets
-
Geographic IP blocking capabilities
-
DDoS protection rules
-
Centralized log management (
/var/log/ubuntu-server-setup.log) -
Structured error reporting
-
System state validation
-
Installation progress tracking
-
Detailed error reports (
.ubuntu-server-setup.error) -
Debug information collection (
.ubuntu-server-setup.debug) -
Automatic cleanup on failures
-
System state restoration
-
Ubuntu 20.04 LTS or newer
-
Minimum 2GB RAM (4GB recommended)
-
Minimum 10GB free disk space
-
Active internet connection
-
Root/sudo access
| Component | Minimum | Recommended |
|---|---|---|
Memory |
2GB |
4GB+ |
Disk Space |
10GB free |
20GB+ free |
CPU Cores |
1 |
2+ |
Network |
100Mbps |
1Gbps+ |
ubuntu-server-setup.sh [OPTIONS]| Option | Type | Description |
|---|---|---|
|
Flag |
Show help message and exit |
|
Flag |
Display script version |
|
Flag |
Auto-confirm all prompts (non-interactive mode) |
|
Flag |
Preview changes without making modifications |
|
Flag |
Generate system report without installing |
|
Flag |
Enable detailed output logging |
|
Parameter |
Admin username for SSH access (required in auto mode) |
|
Parameter |
SSH public key for admin user (required in auto mode) |
|
Parameter |
SSH public key for recovery admin (optional) |
|
Parameter |
DEPRECATED: Use |
sudo ./ubuntu-server-setup.shThe script will guide you through:
-
Admin User Setup - Create non-root admin with sudo access
-
Orchestrator Choice - Select k3s Kubernetes or Docker Swarm
-
Port Configuration - Custom port assignment for services
-
SSL Setup - Domain and email configuration for certificates
-
SSH Key Management - Public key installation for admin user
-
Recovery Admin - Optional failsafe admin account
sudo ./ubuntu-server-setup.sh --yes --admin-user containeruser --admin-key "ssh-ed25519 AAAA..."Uses default settings but requires admin user and SSH key.
sudo ./ubuntu-server-setup.sh --yes \
--admin-user containeruser \
--admin-key "ssh-ed25519 AAAA... primary@host" \
--recovery-key "ssh-rsa BBBB... recovery@vault"sudo ./ubuntu-server-setup.sh --dry-runShows what would be installed/configured without making changes.
The interactive wizard guides you through:
-
Welcome and System Check
-
Root permission verification
-
Ubuntu version validation
-
System requirements check
-
-
Admin User Configuration
-
Username selection (non-root)
-
SSH key installation
-
Optional recovery admin setup
-
-
Orchestrator Selection
-
k3s (Lightweight Kubernetes) - Recommended
-
Docker Swarm - Simpler multi-node clustering
-
-
Port Configuration
-
SSH port assignment (default: 2222)
-
k3s API port (default: 6443)
-
Custom port ranges
-
Conflict detection
-
-
SSL Certificate Setup
-
Domain name configuration
-
Email for Let’s Encrypt notifications
-
Certificate type selection
-
-
Service Configuration Review
-
Component selection confirmation
-
Configuration summary
-
Final installation approval
-
The script uses a configuration file (/etc/server-ports.conf) to manage port assignments:
# Server Port Configuration
SSH_PORT=2222
K3S_API_PORT=6443
DOCKER_PORT=2376
CERTBOT_HTTP_PORT=80
CERTBOT_HTTPS_PORT=443Location: /etc/nginx/sites-available/container-router
server {
listen 80 default_server;
server_name _;
# Default landing page
location / {
root /var/www/html;
index index.html;
}
# Example: Route to container service
location /myapp {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Health check endpoint
location /health {
return 200 "healthy\n";
}
}Nginx Features:
-
Reverse proxy for container services
-
Load balancing capabilities
-
SSL/TLS termination (configured automatically by Certbot)
-
HTTP/2 support
-
Container routing template ready for customization
Adding Container Routes:
# Edit the Nginx configuration
sudo nano /etc/nginx/sites-available/container-router
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginxLocation: /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"exec-opts": ["native.cgroupdriver=systemd"]
}Location: /etc/systemd/system/k3s.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/local/bin/k3s server \
--kube-apiserver-arg=audit-log-path=/var/log/k3s-audit.log \
--kube-apiserver-arg=audit-policy-file=/var/lib/rancher/k3s/server/audit-policy.yaml \
--kube-apiserver-arg=enable-admission-plugins=NodeRestriction,ResourceQuota \
--https-listen-port=${K3S_API_PORT}| Variable | Default | Description |
|---|---|---|
|
|
Script filename |
|
|
Current script version |
|
|
Primary log file location |
|
|
Error report file |
|
|
Debug information file |
The script implements a defense-in-depth security model with multiple layers:
-
Root Access Isolation (No direct root SSH - sudo elevation only)
-
Network Security (UFW Firewall + Port Obfuscation)
-
Access Control (SSH Hardening + Key-based Auth)
-
Intrusion Prevention (Fail2Ban + SSHGuard)
-
Container Security (k3s Hardening + PSP)
-
System Security (Kernel Hardening + Updates)
|
Important
|
Direct root SSH login is DISABLED (PermitRootLogin no).
|
┌──────────────────────────────────────────────────────────┐
│ SSH CONNECTION │
│ (Key-based only) │
└────────────────────────┬─────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ ADMIN USER │
│ (e.g., containeruser) │
│ - Container management │
│ - System monitoring │
│ - Limited user operations │
└────────────────────────┬─────────────────────────────────┘
│
▼ sudo -i / sudo <command>
┌──────────────────────────────────────────────────────────┐
│ ROOT ACCESS │
│ (Via sudo elevation only) │
│ - System administration │
│ - Security configuration │
│ - Service management │
└──────────────────────────────────────────────────────────┘# Connect as admin user
ssh -p <SSH_PORT> admin_username@server_ip
# Run single command as root
sudo apt update
# Get full root shell
sudo -i
# Switch to root (alternative)
sudo su -| Item | Configuration | Status |
|---|---|---|
Password Authentication |
Disabled |
✓ |
Root Login |
Disabled (PermitRootLogin no) |
✓ |
Protocol Version |
SSH-2 Only |
✓ |
Port |
Custom (Non-22) |
✓ |
Key Authentication |
RSA/ED25519 |
✓ |
Connection Rate Limiting |
MaxAuthTries=3 |
✓ |
-
Incoming: DENY (whitelist approach)
-
Outgoing: ALLOW (with monitoring)
-
Routed: DENY
-
Automatic certificate generation
-
90-day renewal automation
-
Multi-domain support (SAN certificates)
-
HTTP-01 and DNS-01 challenge support
-
Auth Logs:
/var/log/auth.log(SSH attempts) -
System Logs:
/var/log/syslog(system events) -
Application Logs:
/var/log/ubuntu-server-setup.log(script events)
# Check script permissions
ls -la ubuntu-server-setup.sh
# Verify syntax
bash -n ubuntu-server-setup.sh
# Check system requirements
df -h /
free -h# Check port usage
ss -tuln | grep :2222
# Find process using port
lsof -i :2222
# Kill conflicting process
sudo systemctl stop <service>Port Conflict with SSH:
If k3s fails to start with "service did not take the steps required", check for port conflicts:
# Check k3s service status
sudo systemctl status k3s
sudo journalctl -xeu k3s.service
# Check port configuration
cat /etc/server-ports.conf
# If k3s port conflicts with SSH port, fix it:
sudo nano /etc/server-ports.conf
# Change: K3S_API_PORT=4444 (wrong - conflicts with SSH)
# To: K3S_API_PORT=6443 (correct - default k3s port)
# Uninstall failed k3s installation
sudo /usr/local/bin/k3s-uninstall.sh
# Re-run the setup script
sudo ./ubuntu-server-setup.shCommon k3s Issues:
-
Port 6443 already in use → Change K3S_API_PORT in config
-
Insufficient memory → Need at least 2GB RAM for k3s
-
Network issues → Check firewall allows k3s ports
-
SELinux blocking → Usually not an issue on Ubuntu
# Check service status
systemctl status docker k3s sshguard fail2ban
# View service logs
journalctl -u docker -f
journalctl -u k3s -fWhy certificates might not be obtained during setup:
-
DNS not configured: Domain must resolve to your server IP before certificates can be obtained
-
Port 80 blocked: Certificate validation requires port 80 to be accessible from the internet
-
Timing: DNS changes can take time to propagate (up to 24-48 hours)
# Check if domain resolves to your server
dig +short yourdomain.com
# Test certificate obtaining manually
sudo certbot certonly --standalone -d yourdomain.com
# Test certificate renewal
sudo certbot renew --dry-run
# Check certificate status
sudo certbot certificatesIf the setup report shows "SSH service is not running", your server may be inaccessible:
# Access server via console/VNC/KVM/cloud console
sudo -i
# Check SSH service status
systemctl status sshd
systemctl status ssh
# Try to start SSH service
systemctl start sshd
# or
systemctl start ssh
# If that fails, check configuration
sshd -t # Test SSH config syntax
# Check logs for errors
journalctl -u sshd -n 50
journalctl -u ssh -n 50
# Fix common issues:
# 1. Port conflict (check if port is in use)
netstat -tlnp | grep :${SSH_PORT}
# 2. Configuration error (restore backup)
cp /etc/ssh/sshd_config.backup.* /etc/ssh/sshd_config
systemctl restart sshdIMPORTANT: If you lose SSH access, use one of these recovery methods:
Option 1: Recovery Admin Account
# If recovery admin was configured during setup
ssh -p <SSH_PORT> recovery_admin@server_ip
sudo -iOption 2: Console Access
# Access server via physical console, KVM, or cloud provider console
# Then temporarily re-enable root login:
sudo nano /etc/ssh/sshd_config
# Change: PermitRootLogin no
# To: PermitRootLogin yes
sudo systemctl restart sshd
# After fixing the issue, disable root login again:
sudo nano /etc/ssh/sshd_config
# Change: PermitRootLogin yes
# To: PermitRootLogin no
sudo systemctl restart sshdOption 3: Single User Mode (Physical Access)
# Boot into recovery mode
# Mount filesystem read-write
mount -o remount,rw /
# Edit sshd_config as needed
nano /etc/ssh/sshd_config
# Reboot
rebootThe script includes comprehensive error handling:
-
Error Detection: Traps all errors with detailed reporting
-
State Validation: Pre and post-installation checks
-
Automatic Cleanup: Removes partial installations on failure
-
Service Recovery: Restores services to known-good states
If automatic recovery fails:
# Check error files
cat .ubuntu-server-setup.error
cat .ubuntu-server-setup.debug
# Reset services
sudo systemctl stop docker k3s sshguard fail2ban
sudo systemctl reset-failed
# Reset firewall
sudo ufw --force reset
sudo ufw enable
# Remove k3s completely
sudo /usr/local/bin/k3s-uninstall.shEnable verbose logging for troubleshooting:
sudo ./ubuntu-server-setup.sh --verbose --dry-runThis provides: * Detailed command execution logs * System state information * Configuration file contents * Service status details
# View installation log
tail -f /var/log/ubuntu-server-setup.log
# Search for errors
grep "ERROR" /var/log/ubuntu-server-setup.log
# Filter by timestamp
grep "2025-12-14" /var/log/ubuntu-server-setup.log# View latest error report
cat .ubuntu-server-setup.error
# Check system state at time of error
cat .ubuntu-server-setup.debug| Service | Port | Purpose | Dependencies |
|---|---|---|---|
Docker CE |
2376 |
Container Runtime |
containerd, runc |
k3s |
6443 |
Kubernetes |
containerd, CNI plugins |
Fail2Ban |
N/A |
Intrusion Prevention |
iptables, systemd |
SSHGuard |
N/A |
SSH Protection |
ufw, iptables |
UFW |
N/A |
Firewall |
iptables, netfilter |
Certbot |
80/443 |
SSL Certificates |
python3, nginx/apache |
The Container/ directory includes additional Docker and Kubernetes management utilities:
-
Docker/remove_dengling_images.sh- Cleanup unused Docker images -
Docker/stop_and_remove_all.sh- Complete Docker environment reset
-
Backup_Tools/Backup_and_Restore_Sources/- Package source management -
Backup_Tools/Backup_Folder/- Filesystem backup utilities
-
List_Installation/- Advanced package list management system -
Program_Setups/- Automated program installation scripts
-
Generate_System_Logs/- Comprehensive system reporting -
System_Configurations/- System optimization scripts
# Backup package sources
cd ../Backup_Tools/Backup_and_Restore_Sources
sudo ./Backup_Source_and_Key.sh
# Run server setup
cd ../../Container
sudo ./ubuntu-server-setup.sh# Install additional development tools
cd ../List_Installation
sudo ./install_list.sh lists/developer.list
# Add custom packages
sudo ./add_pack.sh lists/server.list