137 lines
3.8 KiB
Bash
137 lines
3.8 KiB
Bash
|
|
#!/usr/bin/env sh
|
||
|
|
set -eu
|
||
|
|
|
||
|
|
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||
|
|
PROJECT_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||
|
|
SOURCE_ENV="$PROJECT_ROOT/.env"
|
||
|
|
COMPOSE_SOURCE="$PROJECT_ROOT/docker-compose.yml"
|
||
|
|
BACKUP_TEMPLATE="$SCRIPT_DIR/backup_db.sh"
|
||
|
|
NGINX_TEMPLATE="$SCRIPT_DIR/nginx/moving-helper.nginx.template"
|
||
|
|
NGINX_SITE_NAME="moving-helper-nginx"
|
||
|
|
CRON_MARKER="# moving-helper-backup"
|
||
|
|
|
||
|
|
require_command() {
|
||
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
||
|
|
echo "Missing required command: $1" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
run_as_root() {
|
||
|
|
if [ "$(id -u)" -eq 0 ]; then
|
||
|
|
"$@"
|
||
|
|
elif command -v sudo >/dev/null 2>&1; then
|
||
|
|
sudo "$@"
|
||
|
|
else
|
||
|
|
echo "This step requires root privileges, but sudo is not available: $*" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
escape_sed_replacement() {
|
||
|
|
printf '%s' "$1" | sed 's/[|&]/\\&/g'
|
||
|
|
}
|
||
|
|
|
||
|
|
render_template() {
|
||
|
|
src=$1
|
||
|
|
dst=$2
|
||
|
|
host_domain_escaped=$(escape_sed_replacement "$HOST_DOMAIN")
|
||
|
|
ssl_path_escaped=$(escape_sed_replacement "$SSL_PATH")
|
||
|
|
app_port_escaped=$(escape_sed_replacement "$APP_PORT")
|
||
|
|
app_dir_escaped=$(escape_sed_replacement "$APP_DIR")
|
||
|
|
backup_dir_escaped=$(escape_sed_replacement "$BACKUP_DIR")
|
||
|
|
|
||
|
|
sed \
|
||
|
|
-e "s|__HOST_DOMAIN__|$host_domain_escaped|g" \
|
||
|
|
-e "s|__SSL_PATH__|$ssl_path_escaped|g" \
|
||
|
|
-e "s|__APP_PORT__|$app_port_escaped|g" \
|
||
|
|
-e "s|__APP_DIR__|$app_dir_escaped|g" \
|
||
|
|
-e "s|__BACKUP_DIR__|$backup_dir_escaped|g" \
|
||
|
|
"$src" > "$dst"
|
||
|
|
}
|
||
|
|
|
||
|
|
if [ ! -f "$SOURCE_ENV" ]; then
|
||
|
|
echo "Missing $SOURCE_ENV" >&2
|
||
|
|
echo "Create it first: cp .env.example .env" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
require_command docker
|
||
|
|
require_command crontab
|
||
|
|
|
||
|
|
if ! docker compose version >/dev/null 2>&1; then
|
||
|
|
echo "The docker compose plugin is not available in the current environment" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
set -a
|
||
|
|
. "$SOURCE_ENV"
|
||
|
|
set +a
|
||
|
|
|
||
|
|
HOST_DOMAIN=${HOST_DOMAIN:-}
|
||
|
|
SSL_PATH=${SSL_PATH:-}
|
||
|
|
APP_DIR=${APP_DIR:-$HOME/.local/share/moving-helper}
|
||
|
|
BACKUP_DIR=${BACKUP_DIR:-$HOME/.local/backup/moving-helper}
|
||
|
|
APP_PORT=${APP_PORT:-10000}
|
||
|
|
DATA_DIR=${DATA_DIR:-./data}
|
||
|
|
|
||
|
|
if [ -z "$HOST_DOMAIN" ]; then
|
||
|
|
echo "HOST_DOMAIN is not configured" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ -z "$SSL_PATH" ]; then
|
||
|
|
echo "SSL_PATH is not configured" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
mkdir -p "$APP_DIR" "$BACKUP_DIR" "$APP_DIR/logs"
|
||
|
|
|
||
|
|
case "$DATA_DIR" in
|
||
|
|
/*) mkdir -p "$DATA_DIR" ;;
|
||
|
|
*) mkdir -p "$APP_DIR/$DATA_DIR" ;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
cp "$COMPOSE_SOURCE" "$APP_DIR/docker-compose.yml"
|
||
|
|
cp "$SOURCE_ENV" "$APP_DIR/.env"
|
||
|
|
|
||
|
|
rendered_backup=$(mktemp)
|
||
|
|
rendered_nginx=$(mktemp)
|
||
|
|
trap 'rm -f "$rendered_backup" "$rendered_nginx"' EXIT INT TERM
|
||
|
|
|
||
|
|
render_template "$BACKUP_TEMPLATE" "$rendered_backup"
|
||
|
|
install -m 0755 "$rendered_backup" "$APP_DIR/backup_db.sh"
|
||
|
|
|
||
|
|
render_template "$NGINX_TEMPLATE" "$rendered_nginx"
|
||
|
|
run_as_root install -d /etc/nginx/sites-available /etc/nginx/sites-enabled
|
||
|
|
run_as_root install -m 0644 "$rendered_nginx" "/etc/nginx/sites-available/$NGINX_SITE_NAME"
|
||
|
|
run_as_root ln -sfn "/etc/nginx/sites-available/$NGINX_SITE_NAME" "/etc/nginx/sites-enabled/$NGINX_SITE_NAME"
|
||
|
|
|
||
|
|
run_as_root nginx -t
|
||
|
|
if command -v systemctl >/dev/null 2>&1; then
|
||
|
|
run_as_root systemctl reload nginx
|
||
|
|
else
|
||
|
|
run_as_root service nginx reload
|
||
|
|
fi
|
||
|
|
|
||
|
|
(
|
||
|
|
cd "$APP_DIR"
|
||
|
|
docker compose pull web
|
||
|
|
docker compose up -d
|
||
|
|
)
|
||
|
|
|
||
|
|
cron_tmp=$(mktemp)
|
||
|
|
existing_cron=$(mktemp)
|
||
|
|
trap 'rm -f "$rendered_backup" "$rendered_nginx" "$cron_tmp" "$existing_cron"' EXIT INT TERM
|
||
|
|
|
||
|
|
crontab -l 2>/dev/null > "$existing_cron" || true
|
||
|
|
grep -v "moving-helper-backup" "$existing_cron" > "$cron_tmp" || true
|
||
|
|
printf '10 2 * * * %s/backup_db.sh >> %s/logs/backup.log 2>&1 %s\n' "$APP_DIR" "$APP_DIR" "$CRON_MARKER" >> "$cron_tmp"
|
||
|
|
crontab "$cron_tmp"
|
||
|
|
|
||
|
|
echo "Installation complete."
|
||
|
|
echo "- Application directory: $APP_DIR"
|
||
|
|
echo "- Backup directory: $BACKUP_DIR"
|
||
|
|
echo "- Nginx config: /etc/nginx/sites-available/$NGINX_SITE_NAME"
|
||
|
|
echo "- URL: https://$HOST_DOMAIN"
|
||
|
|
echo "- Scheduled backup: daily at 02:10 via the current user's crontab"
|