Add complete production deployment stack so Timmy can be deployed to any cloud provider (DigitalOcean, AWS, Hetzner, etc.) with a single command. New files: - docker-compose.prod.yml: production stack (Caddy auto-HTTPS, Ollama LLM, Dashboard, Timmy agent, Watchtower auto-updates) - deploy/Caddyfile: reverse proxy with security headers and WebSocket support - deploy/setup.sh: interactive one-click setup script for any Ubuntu/Debian server - deploy/cloud-init.yaml: paste as User Data when creating a cloud VM - deploy/timmy.service: systemd unit for auto-start on boot - deploy/digitalocean/create-droplet.sh: create a DO droplet via doctl CLI Updated: - Dockerfile: non-root user, healthcheck, missing deps (GitPython, moviepy, redis) - Makefile: cloud-deploy, cloud-up/down/logs/status/update/scale targets - .env.example: DOMAIN setting for HTTPS - .dockerignore: exclude deploy configs from image https://claude.ai/code/session_018CduUZoEJzFynBwMsxaP8T
115 lines
3.3 KiB
Bash
Executable File
115 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ── Timmy Time — DigitalOcean Droplet Creator ────────────────────────────────
|
|
#
|
|
# Creates a DigitalOcean Droplet with Timmy pre-installed via cloud-init.
|
|
#
|
|
# Prerequisites:
|
|
# - doctl CLI installed (https://docs.digitalocean.com/reference/doctl/)
|
|
# - doctl auth init (authenticated)
|
|
#
|
|
# Usage:
|
|
# bash deploy/digitalocean/create-droplet.sh
|
|
# bash deploy/digitalocean/create-droplet.sh --domain timmy.example.com
|
|
# bash deploy/digitalocean/create-droplet.sh --size s-2vcpu-4gb --region nyc1
|
|
|
|
BOLD='\033[1m'
|
|
GREEN='\033[0;32m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
# Defaults
|
|
DROPLET_NAME="timmy-mission-control"
|
|
REGION="nyc1"
|
|
SIZE="s-2vcpu-4gb" # 2 vCPU, 4GB RAM — good for llama3.2
|
|
IMAGE="ubuntu-24-04-x64"
|
|
DOMAIN=""
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--name) DROPLET_NAME="$2"; shift 2 ;;
|
|
--region) REGION="$2"; shift 2 ;;
|
|
--size) SIZE="$2"; shift 2 ;;
|
|
--domain) DOMAIN="$2"; shift 2 ;;
|
|
*) echo "Unknown option: $1"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# Check doctl
|
|
if ! command -v doctl &> /dev/null; then
|
|
echo "Error: doctl is not installed."
|
|
echo "Install it: https://docs.digitalocean.com/reference/doctl/how-to/install/"
|
|
exit 1
|
|
fi
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
CLOUD_INIT="$SCRIPT_DIR/../cloud-init.yaml"
|
|
|
|
if [ ! -f "$CLOUD_INIT" ]; then
|
|
echo "Error: cloud-init.yaml not found at $CLOUD_INIT"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${CYAN}${BOLD}"
|
|
echo " Creating DigitalOcean Droplet"
|
|
echo " ─────────────────────────────"
|
|
echo -e "${NC}"
|
|
echo " Name: $DROPLET_NAME"
|
|
echo " Region: $REGION"
|
|
echo " Size: $SIZE"
|
|
echo " Image: $IMAGE"
|
|
echo ""
|
|
|
|
# Create the droplet
|
|
DROPLET_ID=$(doctl compute droplet create "$DROPLET_NAME" \
|
|
--region "$REGION" \
|
|
--size "$SIZE" \
|
|
--image "$IMAGE" \
|
|
--user-data-file "$CLOUD_INIT" \
|
|
--enable-monitoring \
|
|
--format ID \
|
|
--no-header \
|
|
--wait)
|
|
|
|
echo -e "${GREEN}[+]${NC} Droplet created: ID $DROPLET_ID"
|
|
|
|
# Get the IP
|
|
sleep 5
|
|
IP=$(doctl compute droplet get "$DROPLET_ID" --format PublicIPv4 --no-header)
|
|
echo -e "${GREEN}[+]${NC} Public IP: $IP"
|
|
|
|
# Set up DNS if domain provided
|
|
if [ -n "$DOMAIN" ]; then
|
|
# Extract the base domain (last two parts)
|
|
BASE_DOMAIN=$(echo "$DOMAIN" | awk -F. '{print $(NF-1)"."$NF}')
|
|
SUBDOMAIN=$(echo "$DOMAIN" | sed "s/\.$BASE_DOMAIN$//")
|
|
|
|
if [ "$SUBDOMAIN" = "$DOMAIN" ]; then
|
|
SUBDOMAIN="@"
|
|
fi
|
|
|
|
echo -e "${GREEN}[+]${NC} Creating DNS record: $DOMAIN -> $IP"
|
|
doctl compute domain records create "$BASE_DOMAIN" \
|
|
--record-type A \
|
|
--record-name "$SUBDOMAIN" \
|
|
--record-data "$IP" \
|
|
--record-ttl 300 || echo " (DNS record creation failed — set it manually)"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${GREEN}${BOLD} Droplet is provisioning!${NC}"
|
|
echo ""
|
|
echo " The server will be ready in ~3-5 minutes."
|
|
echo ""
|
|
echo " SSH in: ssh root@$IP"
|
|
echo " Check progress: ssh root@$IP tail -f /var/log/cloud-init-output.log"
|
|
if [ -n "$DOMAIN" ]; then
|
|
echo " Dashboard: https://$DOMAIN (after DNS propagation)"
|
|
fi
|
|
echo " Dashboard: http://$IP"
|
|
echo ""
|
|
echo " After boot, edit /opt/timmy/.env to set your domain and secrets."
|
|
echo ""
|