Version: Jun 2, 2025

DreblowDesignsWebServer

Dreblow Designs server

Getting Started

This blog sets up a reverse proxy with automatic HTTPS using NGINX for website hosting and Let's Encrypt for SSL certificate. These are guides I've written based on setting up and maintaining my own production-grade Ubuntu server using Docker, NGINX, and shell scripts β€” fully open source and self-hosted.

Check out the required Docker Compose files for the server and sites:

Prerequisites


Setup

Clone the repo:

git clone git@github.com:Dreblow/DreblowDesignsWebServer.git
cd DreblowDesignsWebServer

Run the setup script:

sudo chmod +x setup.sh && ./setup.sh

This will:

Push the update over SSH:

ssh dreblow@<your_ip> '~/git/DreblowDesignsWebServer/setup.sh'

Take it one stop further and add as an alias on the Mac:

Add this to your nano ~/.zshrc or nano /.bash_profile:

alias deployserver="ssh dreblow@<your_ip> '~/git/DreblowDesignsWebServer/setup.sh'"

Then run:

source ~/.zshrc   # or ~/.bash_profile

Now anytime you want to deploy from terminal:

deployserver

Done!!

Here is mine in real life:

# Alias to invoke script on server
alias localdeploy='ssh dre@192.168.1.### "bash ~/git/DreblowDesignsWebServer/setup.sh"'           # Local IP
alias remotedeploy='ssh -p 6## dre@##.##.###.### "bash ~/git/DreblowDesignsWebServer/setup.sh"'   # Public IP 

# Optional: enable tab-completion for aliases
setopt complete_aliases                                                                           # Have to have tab auto complete

Setup.sh

This script automates the entire web server deployment:

Step-by-Step Breakdown

  1. Shebang + Error Handling
#!/bin/bash
set -e
# Prevent running as root (with sudo)
if [ "$EUID" -eq 0 ]; then
  echo "❌ Do not run this script with sudo. Exiting.."
  exit 1
fi
  1. Introduction Output
echo "πŸš€ Launching Dreblow Designs Web Server setup..."
  1. Settings Block
GIT_ROOT="$HOME/git"
DEPLOY_ROOT="/srv/sites"
REPOS=(
    # Add more repos here, no commas needed
  "git@github.com:Dreblow/WebSite_DreblowDesigns.git"
  "git@github.com:Dreblow/WebSite_MathSheetGen.git"
  "git@github.com:Dreblow/WebSite_DreblowandAssociates.git"
)
  1. Directory Setup
if [ ! -d "$GIT_ROOT" ]; then
  sudo mkdir -p "$GIT_ROOT"
fi
if [ ! -d "$DEPLOY_ROOT" ]; then
  sudo mkdir -p "$DEPLOY_ROOT"
fi
sudo chown -R "$USER" "$GIT_ROOT" "$DEPLOY_ROOT"
  1. Repo Cloning & Deployment Loop
for REPO in "${REPOS[@]}"; do
  NAME=$(basename "$REPO" .git)
  DOMAIN="$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | sed 's/website_//g').com"

  LOCAL_REPO="$GIT_ROOT/$NAME"
  if [ -d "$LOCAL_REPO" ]; then
    echo "πŸ—‘οΈ Removing old repository at $LOCAL_REPO..."
    rm -rf "$LOCAL_REPO"
  fi

  if [ -d "$DEPLOY_ROOT/$DOMAIN" ]; then
    echo "πŸ—‘οΈ Removing deployed site at $DEPLOY_ROOT/$DOMAIN..."
    rm -rf "$DEPLOY_ROOT/$DOMAIN"
  fi

  if [ -d "$GIT_ROOT/$NAME/.git" ]; then
    git -C "$GIT_ROOT/$NAME" pull
  else
    git clone "$REPO" "$GIT_ROOT/$NAME"
  fi

  mkdir -p "$DEPLOY_ROOT/$DOMAIN"
  rsync -av --delete "$GIT_ROOT/$NAME/" "$DEPLOY_ROOT/$DOMAIN/" \
    --exclude ".git" --exclude "resources/dev" --exclude "node_modules"
done
  1. Docker Network Setup
docker network inspect webproxy >/dev/null 2>&1 || \ docker network create webproxy
  1. Start Reverse Proxy Stack
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
docker compose -f "$SCRIPT_DIR/docker/server/docker-compose.yml" up -d
docker compose -f "$SCRIPT_DIR/docker/sites/docker-compose.yml" up -d
  1. Wrap-up
echo "βœ… All websites are deployed and live with HTTPS support."

  1. The entire script
#!/bin/bash

# Super clean, Super Bias, Dreblow Designs Server Setup Script
# This script owns all deployments. Websites are dumb. Server is smart.

set -e

# Prevent running as root (with sudo)
if [ "$EUID" -eq 0 ]; then
  echo "❌ Do not run this script with sudo. Exiting.."
  exit 1
fi

echo "πŸš€ Launching Dreblow Designs Web Server setup..."

# === SETTINGS ===
GIT_ROOT="$HOME/git"
DEPLOY_ROOT="/srv/sites"
REPOS=(
  "git@github.com:Dreblow/WebSite_DreblowDesigns.git"
  "git@github.com:Dreblow/WebSite_MathSheetGen.git"
  "git@github.com:Dreblow/WebSite_DreblowandAssociates.git"
  # Add more repos here
)

# === PREP DIRECTORIES ===
echo "πŸ“ Ensuring base directories exist..."
if [ ! -d "$GIT_ROOT" ]; then
  echo "πŸ“ Creating git directory at $GIT_ROOT"
  sudo mkdir -p "$GIT_ROOT"
else
  echo "βœ… Git directory exists at $GIT_ROOT"
fi

if [ ! -d "$DEPLOY_ROOT" ]; then
  echo "πŸ“ Creating deploy directory at $DEPLOY_ROOT"
  sudo mkdir -p "$DEPLOY_ROOT"
else
  echo "βœ… Deploy directory exists at $DEPLOY_ROOT"
fi

sudo chown -R "$USER" "$GIT_ROOT" "$DEPLOY_ROOT"

# === CLONE & DEPLOY ===
echo "πŸ“¦ Cloning and copying website files..."
for REPO in "${REPOS[@]}"; do
  NAME=$(basename "$REPO" .git)
  DOMAIN="$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | sed 's/website_//g').com"
  
  LOCAL_REPO="$GIT_ROOT/$NAME"
  if [ -d "$LOCAL_REPO" ]; then
    echo "πŸ—‘οΈ Removing old repository at $LOCAL_REPO..."
    rm -rf "$LOCAL_REPO"
  fi

  DOMAIN="$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | sed 's/website_//g').com"

  # Clone or pull
  if [ -d "$GIT_ROOT/$NAME/.git" ]; then
    echo "πŸ”„ Updating $NAME..."
    git -C "$GIT_ROOT/$NAME" pull
  else
    echo "πŸ“₯ Cloning $NAME..."
    git clone "$REPO" "$GIT_ROOT/$NAME"
  fi

  # Copy static content
  echo "πŸ“€ Deploying to $DEPLOY_ROOT/$DOMAIN..."
  mkdir -p "$DEPLOY_ROOT/$DOMAIN"
  rsync -av --delete "$GIT_ROOT/$NAME/" "$DEPLOY_ROOT/$DOMAIN/" \
    --exclude ".git" --exclude "resources/dev" --exclude "node_modules"
done

# === NETWORK SETUP ===
echo "🌐 Ensuring shared Docker network exists..."
docker network inspect webproxy >/dev/null 2>&1 || \
  docker network create webproxy

# === START REVERSE PROXY ===
echo "🧰 Starting NGINX + SSL reverse proxy..."
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
docker compose -f "$SCRIPT_DIR/docker/server/docker-compose.yml" up -d
docker compose -f "$SCRIPT_DIR/docker/sites/docker-compose.yml" up -d

# === DONE ===
echo "βœ… All websites are deployed and live with HTTPS support."