177 lines
6.4 KiB
Bash
Executable File
177 lines
6.4 KiB
Bash
Executable File
#!/bin/bash
|
||
set -e
|
||
|
||
# ── Farben ──────────────────────────────────────────────
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
NC='\033[0m'
|
||
|
||
log() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
||
error() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
|
||
|
||
# ── Konfiguration ────────────────────────────────────────
|
||
APP_DIR="/opt/projects"
|
||
REPO_URL="https://github.com/Fixelx/ProjectApp.git"
|
||
DOMAIN=${1:-"localhost"}
|
||
|
||
echo ""
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo " ProjectApp Deployment"
|
||
echo " Domain: $DOMAIN"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo ""
|
||
|
||
# ── Root check ───────────────────────────────────────────
|
||
[ "$EUID" -ne 0 ] && error "Bitte als root ausführen (sudo ./deploy.sh)"
|
||
|
||
# ── System-Pakete ────────────────────────────────────────
|
||
log "System-Pakete installieren..."
|
||
apt update -q
|
||
apt install -y git nginx curl -q
|
||
|
||
# ── Python Version erkennen und richtige Pakete installieren ──
|
||
log "Python einrichten..."
|
||
PYTHON_BIN=""
|
||
|
||
# Python 3.13 vorhanden?
|
||
if python3 --version 2>/dev/null | grep -q "3.13"; then
|
||
log "Python 3.13 erkannt"
|
||
apt install -y python3.13-venv -q || true
|
||
# pip über get-pip.py installieren da python3-pip inkompatibel
|
||
curl -sS https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py
|
||
python3 /tmp/get-pip.py --break-system-packages -q
|
||
PYTHON_BIN="python3"
|
||
# Python 3.11 vorhanden?
|
||
elif python3.11 --version 2>/dev/null; then
|
||
log "Python 3.11 erkannt"
|
||
apt install -y python3.11 python3.11-venv python3-pip -q
|
||
PYTHON_BIN="python3.11"
|
||
# Fallback: Python 3 installieren
|
||
else
|
||
log "Python 3.11 installieren..."
|
||
apt install -y python3 python3-venv python3-pip -q
|
||
PYTHON_BIN="python3"
|
||
fi
|
||
|
||
log "Python-Binary: $PYTHON_BIN ($($PYTHON_BIN --version))"
|
||
|
||
# ── Repo ─────────────────────────────────────────────────
|
||
if [ -d "$APP_DIR/.git" ]; then
|
||
log "Repo aktualisieren..."
|
||
cd $APP_DIR
|
||
git pull origin main
|
||
else
|
||
log "Repo klonen..."
|
||
git clone $REPO_URL $APP_DIR
|
||
cd $APP_DIR
|
||
fi
|
||
|
||
cd $APP_DIR
|
||
|
||
# ── .env prüfen ──────────────────────────────────────────
|
||
if [ ! -f "$APP_DIR/.env" ]; then
|
||
warn ".env fehlt – wird aus .env.example erstellt..."
|
||
cp $APP_DIR/.env.example $APP_DIR/.env
|
||
|
||
SECRET=$($PYTHON_BIN -c "import secrets; print(secrets.token_urlsafe(50))")
|
||
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=$SECRET/" $APP_DIR/.env
|
||
sed -i "s/^ALLOWED_HOSTS=.*/ALLOWED_HOSTS=$DOMAIN,localhost/" $APP_DIR/.env
|
||
sed -i "s/^CSRF_TRUSTED_ORIGINS=.*/CSRF_TRUSTED_ORIGINS=https:\/\/$DOMAIN/" $APP_DIR/.env
|
||
|
||
warn ".env wurde angelegt – bitte prüfen: nano $APP_DIR/.env"
|
||
fi
|
||
|
||
# ── Python venv ──────────────────────────────────────────
|
||
log "Virtualenv einrichten..."
|
||
$PYTHON_BIN -m venv $APP_DIR/venv
|
||
source $APP_DIR/venv/bin/activate
|
||
|
||
# ── Abhängigkeiten ───────────────────────────────────────
|
||
log "Python-Pakete installieren..."
|
||
pip install --upgrade pip -q
|
||
pip install -r $APP_DIR/requirements.txt -q
|
||
pip install gunicorn -q
|
||
|
||
# ── Django setup ─────────────────────────────────────────
|
||
log "Migrationen ausführen..."
|
||
python manage.py migrate --no-input
|
||
|
||
log "Static files sammeln..."
|
||
python manage.py collectstatic --no-input
|
||
|
||
# ── Gunicorn Service ─────────────────────────────────────
|
||
log "Gunicorn Service einrichten..."
|
||
cat > /etc/systemd/system/gunicorn.service << EOF
|
||
[Unit]
|
||
Description=Gunicorn für ProjectApp
|
||
After=network.target
|
||
|
||
[Service]
|
||
User=root
|
||
Group=www-data
|
||
WorkingDirectory=$APP_DIR
|
||
EnvironmentFile=$APP_DIR/.env
|
||
ExecStart=$APP_DIR/venv/bin/gunicorn \\
|
||
--workers 3 \\
|
||
--bind unix:$APP_DIR/gunicorn.sock \\
|
||
config.wsgi:application
|
||
Restart=always
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable gunicorn -q
|
||
systemctl restart gunicorn
|
||
|
||
# ── Nginx config ─────────────────────────────────────────
|
||
log "Nginx konfigurieren..."
|
||
cat > /etc/nginx/sites-available/projectapp << EOF
|
||
server {
|
||
listen 80;
|
||
server_name $DOMAIN;
|
||
|
||
location /static/ {
|
||
alias $APP_DIR/staticfiles/;
|
||
}
|
||
|
||
location /media/ {
|
||
alias $APP_DIR/media/;
|
||
}
|
||
|
||
location / {
|
||
proxy_pass http://unix:$APP_DIR/gunicorn.sock;
|
||
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;
|
||
}
|
||
}
|
||
EOF
|
||
|
||
[ -f /etc/nginx/sites-enabled/default ] && rm /etc/nginx/sites-enabled/default
|
||
|
||
ln -sf /etc/nginx/sites-available/projectapp /etc/nginx/sites-enabled/
|
||
nginx -t && systemctl restart nginx
|
||
|
||
# ── Superuser ────────────────────────────────────────────
|
||
warn "Superuser anlegen? [j/N]"
|
||
read -r SU
|
||
if [ "$SU" = "j" ] || [ "$SU" = "J" ]; then
|
||
python manage.py createsuperuser
|
||
fi
|
||
|
||
# ── Fertig ───────────────────────────────────────────────
|
||
echo ""
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
log "Deployment abgeschlossen!"
|
||
echo ""
|
||
echo " App erreichbar unter: http://$DOMAIN"
|
||
echo " .env prüfen: nano $APP_DIR/.env"
|
||
echo " Logs: journalctl -u gunicorn -f"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo ""
|