From f5986090c02e699b7bfdfc22dfffeb18e1ddf693 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Mon, 16 Mar 2026 09:51:29 +0100 Subject: [PATCH] feat(deploy) : add deploy script and nginx config for bare Ubuntu server Co-Authored-By: Claude Opus 4.6 --- deploy/nginx/lesstime.conf | 50 +++++++++++++++++++++ script/deploy-release.sh | 91 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 deploy/nginx/lesstime.conf create mode 100755 script/deploy-release.sh diff --git a/deploy/nginx/lesstime.conf b/deploy/nginx/lesstime.conf new file mode 100644 index 0000000..2202b76 --- /dev/null +++ b/deploy/nginx/lesstime.conf @@ -0,0 +1,50 @@ +server { + listen 80; + server_name project.malio-dev.fr; + + root /var/www/lesstime/frontend/.output/public; + index index.html; + + client_max_body_size 55m; + + location ^~ /api/ { + root /var/www/lesstime/public; + try_files $uri /index.php?$query_string; + } + + location ^~ /bundles/ { + root /var/www/lesstime/public; + try_files $uri =404; + } + + location = /api/login_check { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /var/www/lesstime/public/index.php; + fastcgi_param DOCUMENT_ROOT /var/www/lesstime/public; + fastcgi_param SCRIPT_NAME /index.php; + fastcgi_param PATH_INFO /login_check; + fastcgi_param REQUEST_URI /login_check; + fastcgi_pass unix:/run/php/php8.4-fpm.sock; + } + + location ^~ /_mcp { + root /var/www/lesstime/public; + try_files $uri /index.php?$query_string; + } + + location ~ ^/index\.php(/|$) { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /var/www/lesstime/public/index.php; + fastcgi_param DOCUMENT_ROOT /var/www/lesstime/public; + fastcgi_pass unix:/run/php/php8.4-fpm.sock; + internal; + } + + location ~ \.php$ { + return 404; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/script/deploy-release.sh b/script/deploy-release.sh new file mode 100755 index 0000000..80efe12 --- /dev/null +++ b/script/deploy-release.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Usage: ./script/deploy-release.sh v0.1.0 +# Requires: curl, tar, (optional) rsync +# +# Auth token: set RELEASE_TOKEN env var or create /etc/lesstime-release-token +umask 002 + +TAG="${1:-}" +if [ -z "$TAG" ]; then + echo "Usage: $0 v0.1.0" >&2 + exit 1 +fi + +REPO_OWNER="MALIO-DEV" +REPO_NAME="Lesstime" +GITEA_API="https://gitea.malio.fr/api/v1" +DEPLOY_DIR="/var/www/lesstime" + +if [ -f /etc/lesstime-release-token ] && [ -z "${RELEASE_TOKEN:-}" ]; then + RELEASE_TOKEN="$(cat /etc/lesstime-release-token)" +fi + +tmp_dir="$(mktemp -d)" +cleanup() { + rm -rf "$tmp_dir" +} +trap cleanup EXIT + +release_json="$tmp_dir/release.json" +curl_opts=(-sS) +if [ -n "${RELEASE_TOKEN:-}" ]; then + curl_opts+=(-H "Authorization: token ${RELEASE_TOKEN}") +fi +curl "${curl_opts[@]}" \ + "${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/releases/tags/${TAG}" \ + -o "$release_json" + +asset_url="$(python3 - "$release_json" <<'PY' +import json, sys +data = json.load(open(sys.argv[1], 'r')) +assets = data.get("assets", []) +for a in assets: + name = a.get("name", "") + if name.startswith("lesstime-") and name.endswith(".tar.gz"): + print(a.get("browser_download_url", "")) + break +PY +)" + +if [ -z "$asset_url" ]; then + echo "Release asset not found for tag ${TAG}" >&2 + exit 1 +fi + +archive="$tmp_dir/artefact.tar.gz" +curl "${curl_opts[@]}" -L "$asset_url" -o "$archive" + +tar -xzf "$archive" -C "$tmp_dir" + +if command -v rsync >/dev/null 2>&1; then + rsync -a --delete --no-perms --no-owner --no-group \ + --exclude ".env" \ + --exclude ".env.local" \ + --exclude "config/jwt" \ + --exclude "var" \ + "$tmp_dir"/ "$DEPLOY_DIR"/ +else + cp -a "$tmp_dir"/. "$DEPLOY_DIR"/ +fi + +# Ensure Nginx can traverse the deploy path. +chmod o+rx "$(dirname "$DEPLOY_DIR")" "$DEPLOY_DIR" 2>/dev/null || true + +# Create frontend/dist symlink if needed (nginx serves from frontend/dist) +if [ -d "${DEPLOY_DIR}/frontend/.output/public" ] && [ ! -L "${DEPLOY_DIR}/frontend/dist" ]; then + ln -sfn "${DEPLOY_DIR}/frontend/.output/public" "${DEPLOY_DIR}/frontend/dist" +fi + +echo "Release ${TAG} deployed to ${DEPLOY_DIR}" + +if [ -f "${DEPLOY_DIR}/.env.local" ]; then + echo "Clearing cache..." + php "${DEPLOY_DIR}/bin/console" cache:clear --env=prod --no-debug + + echo "Running migrations (if any)..." + php "${DEPLOY_DIR}/bin/console" doctrine:migrations:migrate --no-interaction --env=prod +else + echo "Skip post-deploy: ${DEPLOY_DIR}/.env.local not found" >&2 +fi