Skip to content

Instantly share code, notes, and snippets.

@konverner
Last active April 6, 2026 12:44
Show Gist options
  • Select an option

  • Save konverner/47e8f6ba0452612cc9954d5fbf8f17bf to your computer and use it in GitHub Desktop.

Select an option

Save konverner/47e8f6ba0452612cc9954d5fbf8f17bf to your computer and use it in GitHub Desktop.
This script prepares a Linux server (Ubuntu) for running web app in production
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
###############################################################################
# Production Server Setup Script
#
# This script prepares a Linux server (Ubuntu) for running a production
# Docker-based web application with HTTPS and automated PostgreSQL backups.
#
# What the script does:
# 1. Installs Docker Engine and Docker Compose (if not already installed)
# 2. Requests an SSL certificate from Let's Encrypt using Certbot
# 3. Creates directories for SSL certificates and Certbot validation
# 4. Configures an automated PostgreSQL backup routine
# 5. Adds a cron job to run backups daily
# 6. Adds automatic SSL certificate renewal
# 7. Configures Docker log rotation (prevents disk overflow)
# 8. Cleans existing Docker container logs
# 9. Validates installation
#
# Usage:
# chmod +x setup.sh
# ./setup.sh
###############################################################################
# --- CONFIGURATION ---
DOMAIN="yourdomain.com"
EMAIL="your-email@example.com"
PROJECT_ROOT="$HOME/yourproject"
BACKUP_DIR="/root/backups/postgres"
echo "🌐 Starting Production Setup for $DOMAIN..."
# ---------------------------------------------------------------------------
# 1. INSTALL DOCKER & DOCKER-COMPOSE (IDEMPOTENT)
# ---------------------------------------------------------------------------
echo "πŸ“¦ Checking Docker installation..."
if ! command -v docker >/dev/null 2>&1; then
echo "Installing Docker and Docker Compose..."
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
else
echo "βœ… Docker already installed"
fi
# ---------------------------------------------------------------------------
# 2. CREATE FOLDERS & SSL CERTIFICATES (IDEMPOTENT)
# ---------------------------------------------------------------------------
echo "πŸ” Setting up SSL folders..."
mkdir -p "$PROJECT_ROOT/certs"
mkdir -p "$PROJECT_ROOT/certbot-www"
if [ ! -f "$PROJECT_ROOT/certs/live/$DOMAIN/fullchain.pem" ]; then
echo "Requesting new SSL certificate..."
sudo fuser -k 80/tcp || true
docker run --rm -it \
-v "$PROJECT_ROOT/certs:/etc/letsencrypt" \
-v "$PROJECT_ROOT/certbot-www:/var/www/certbot" \
-p 80:80 \
certbot/certbot certonly --standalone \
-d "$DOMAIN" --email "$EMAIL" --agree-tos --no-eff-email
sudo chmod -R 755 "$PROJECT_ROOT/certs"
else
echo "βœ… SSL certificate already exists"
fi
# ---------------------------------------------------------------------------
# 3. SET POSTGRES BACKUP ROUTINE
# ---------------------------------------------------------------------------
echo "πŸ’Ύ Configuring Backup Routine..."
mkdir -p "$BACKUP_DIR"
cat <<EOF > "$PROJECT_ROOT/backup.sh"
#!/bin/bash
set -euo pipefail
TIMESTAMP=\$(date +"%Y%m%d_%H%M%S")
docker exec astore-office-db-1 pg_dump -U \${PG_USER:-postgres} \${PG_DB:-astore_db} \
| gzip > $BACKUP_DIR/db_backup_\$TIMESTAMP.sql.gz
find $BACKUP_DIR -type f -mtime +30 -delete
EOF
chmod +x "$PROJECT_ROOT/backup.sh"
(crontab -l 2>/dev/null | grep -v "$PROJECT_ROOT/backup.sh"; \
echo "0 2 * * * /bin/bash $PROJECT_ROOT/backup.sh") | crontab -
# ---------------------------------------------------------------------------
# 4. AUTOMATIC SSL CERTIFICATE RENEWAL
# ---------------------------------------------------------------------------
echo "πŸ” Configuring SSL renewal..."
cat <<EOF > "$PROJECT_ROOT/renew-cert.sh"
#!/bin/bash
set -euo pipefail
docker run --rm \
-v "$PROJECT_ROOT/certs:/etc/letsencrypt" \
-v "$PROJECT_ROOT/certbot-www:/var/www/certbot" \
certbot/certbot renew --webroot -w /var/www/certbot
EOF
chmod +x "$PROJECT_ROOT/renew-cert.sh"
(crontab -l 2>/dev/null | grep -v "$PROJECT_ROOT/renew-cert.sh"; \
echo "0 3 * * * /bin/bash $PROJECT_ROOT/renew-cert.sh") | crontab -
# ---------------------------------------------------------------------------
# 5. CONFIGURE DOCKER LOG ROTATION (PREVENT DISK OVERFLOW)
# ---------------------------------------------------------------------------
echo "🧹 Configuring Docker log rotation..."
DOCKER_DAEMON_CONFIG="/etc/docker/daemon.json"
sudo mkdir -p /etc/docker
if [ ! -f "$DOCKER_DAEMON_CONFIG" ]; then
sudo tee "$DOCKER_DAEMON_CONFIG" > /dev/null <<EOF
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
echo "Restarting Docker service..."
sudo systemctl restart docker
else
echo "Docker daemon config already exists β€” skipping overwrite"
fi
# ---------------------------------------------------------------------------
# 6. CLEAN EXISTING DOCKER LOG FILES
# ---------------------------------------------------------------------------
echo "🧽 Cleaning existing Docker container logs..."
sudo find /var/lib/docker/containers/ -name "*-json.log" \
-exec truncate -s 0 {} \; 2>/dev/null || true
echo "βœ… Existing logs cleared"
# ---------------------------------------------------------------------------
# 7. VALIDATION
# ---------------------------------------------------------------------------
echo "πŸ” Validating Setup..."
echo -n "Checking Docker Compose: "
if docker compose version >/dev/null 2>&1; then echo "βœ… OK"; else echo "❌ FAILED"; fi
echo -n "Checking SSL Certs: "
if [ -f "$PROJECT_ROOT/certs/live/$DOMAIN/fullchain.pem" ]; then echo "βœ… OK"; else echo "❌ FAILED"; fi
echo -n "Checking Backup Cron: "
if crontab -l | grep -q "$PROJECT_ROOT/backup.sh"; then echo "βœ… OK"; else echo "❌ FAILED"; fi
echo -n "Checking SSL Renewal Cron: "
if crontab -l | grep -q "$PROJECT_ROOT/renew-cert.sh"; then echo "βœ… OK"; else echo "❌ FAILED"; fi
echo "-------------------------------------------------------"
echo "βœ… Setup Complete!"
echo ""
echo "Next step:"
echo "Put your docker-compose.yml and .env in:"
echo "$PROJECT_ROOT"
echo ""
echo "Then run:"
echo "docker compose up -d"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment