Last active
April 6, 2026 12:44
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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