diff --git a/mnemo_cards_backend/build_app.sh b/mnemo_cards_backend/build_app.sh new file mode 100644 index 0000000..37aacfa --- /dev/null +++ b/mnemo_cards_backend/build_app.sh @@ -0,0 +1,54 @@ +set -e -v + +cd ~/mnemo_cards_common +git pull origin master +dart pub get + +cd ~/mnemo_cards_common_backend +git pull origin master +dart pub get + +cd ~/mnemo_cards_backend +dart pub get && dart compile exe --verbose lib/main.dart -o server_build.exe + +sudo systemctl stop mnemo_cards_server && true +sleep 15 +sudo chmod 777 mnemo_cards_server.service +sudo cp mnemo_cards_server.service /etc/systemd/system +sudo cp server_build.exe server.exe +rm server_build.exe + +# Проверяем наличие Let's Encrypt сертификатов для двойного режима +if [ -d "/etc/letsencrypt/live/api.memo-cards.online" ]; then + echo "✅ Let's Encrypt сертификаты найдены. Запускаем в двойном режиме (HTTP + HTTPS)" + # Обновляем systemd сервис для двойного режима + sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe --dual --certs /etc/letsencrypt/live/api.memo-cards.online -a 0.0.0.0 -p 8443|' /etc/systemd/system/mnemo_cards_server.service +else + echo "⚠️ Let's Encrypt сертификаты не найдены. Пытаемся создать..." + + # Останавливаем сервер временно для получения сертификата + sudo systemctl stop mnemo_cards_server 2>/dev/null || true + + # Пытаемся получить Let's Encrypt сертификат + echo "🔐 Получаем Let's Encrypt сертификат для домена api.memo-cards.online..." + if sudo certbot certonly --standalone -d api.memo-cards.online --non-interactive --agree-tos --email admin@api.memo-cards.online; then + echo "✅ Let's Encrypt сертификат успешно создан!" + echo "🚀 Запускаем в двойном режиме (HTTP + HTTPS)" + # Обновляем systemd сервис для двойного режима + sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe --dual --certs /etc/letsencrypt/live/api.memo-cards.online -a 0.0.0.0 -p 8443|' /etc/systemd/system/mnemo_cards_server.service + else + echo "❌ Не удалось создать Let's Encrypt сертификат. Запускаем в HTTP режиме" + echo "💡 Убедитесь, что:" + echo " - Домен api.memo-cards.online указывает на этот сервер" + echo " - Порт 80 доступен извне" + echo " - Firewall разрешает входящие соединения на порт 80" + # Возвращаем обычный режим + sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe -a 0.0.0.0 -p 8443|' /etc/systemd/system/mnemo_cards_server.service + fi +fi + +sudo systemctl daemon-reload +sudo systemctl start mnemo_cards_server +journalctl -u mnemo_cards_server --since "1min ago" + + diff --git a/mnemo_cards_web_v2/deploy.sh b/mnemo_cards_web_v2/deploy.sh new file mode 100755 index 0000000..cbaae88 --- /dev/null +++ b/mnemo_cards_web_v2/deploy.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Wrapper script for deploying mnemo_cards_web_v2 +# This script uses the centralized deployment scripts from tools/deploy/web-app/ + +set -e + +# Get the root directory +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +DEPLOY_SCRIPTS_DIR="$ROOT_DIR/tools/deploy/web-app" +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Check if centralized deploy scripts exist +if [ ! -f "$DEPLOY_SCRIPTS_DIR/deploy.sh" ]; then + echo "❌ Error: Centralized deploy scripts not found at $DEPLOY_SCRIPTS_DIR" + exit 1 +fi + +# Change to project directory (required for build to work) +cd "$PROJECT_DIR" + +# Source config and run deploy +source "$DEPLOY_SCRIPTS_DIR/config.sh" +source "$DEPLOY_SCRIPTS_DIR/deploy.sh" + diff --git a/tools/ci/cd-deploy.yml b/tools/ci/cd-deploy.yml deleted file mode 100644 index 70f494b..0000000 --- a/tools/ci/cd-deploy.yml +++ /dev/null @@ -1,92 +0,0 @@ -name: Deploy Applications - -on: - push: - branches: [ main, master ] - workflow_dispatch: - inputs: - component: - description: 'Component to deploy' - required: false - default: 'all' - type: choice - options: - - all - - backend - - web - - mobile - -jobs: - deploy-backend: - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup SSH - uses: webfactory/ssh-agent@v0.9.0 - with: - ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} - - - name: Add server to known hosts - run: | - mkdir -p ~/.ssh - ssh-keyscan -H 147.45.152.129 >> ~/.ssh/known_hosts - - - name: Deploy backend - run: | - cd tools/deploy - chmod +x backend-build_app.sh - ./backend-build_app.sh - - deploy-web: - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup SSH - uses: webfactory/ssh-agent@v0.9.0 - with: - ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} - - - name: Add server to known hosts - run: | - mkdir -p ~/.ssh - ssh-keyscan -H 147.45.152.129 >> ~/.ssh/known_hosts - - - name: Deploy web app - run: | - cd tools/deploy/web-app - chmod +x deploy.sh - ./deploy.sh - - deploy-mobile: - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Create release notes - run: | - echo "🚀 New release from $(date)" > release_notes.md - echo "" >> release_notes.md - echo "## Changes" >> release_notes.md - git log --oneline -10 >> release_notes.md - - - name: Create GitHub release - uses: softprops/action-gh-release@v2 - with: - tag_name: v$(date +%Y%m%d_%H%M%S) - name: "Release $(date +%Y-%m-%d)" - body_path: release_notes.md - draft: false - prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/tools/ci/deploy.yaml b/tools/ci/deploy.yaml new file mode 100644 index 0000000..81ddc2a --- /dev/null +++ b/tools/ci/deploy.yaml @@ -0,0 +1,80 @@ +name: Deploy Mnemo Cards + +on: + workflow_dispatch: + push: + branches: + - master + +jobs: + deploy-backend: + name: Deploy Backend + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts + + - name: Sync Source Code + run: | + # Sync common packages + rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'doc' \ + mnemo_cards_common \ + mnemo_cards_common_backend \ + ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/ + + # Sync backend project + rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'server.exe' \ + mnemo_cards_backend \ + ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/ + + # Sync build script + rsync -avz tools/deploy/backend/server_build.sh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/mnemo_cards_backend/ + ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "chmod +x ~/mnemo_cards_backend/server_build.sh" + + - name: Trigger Remote Build + run: | + ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/mnemo_cards_backend/server_build.sh" + + deploy-web: + name: Deploy Web App + runs-on: ubuntu-latest + needs: deploy-backend + if: always() # Run even if backend fails (optional, but usually good to separate) + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: '3.19.2' # Adjust version as needed + channel: 'stable' + + - name: Setup SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts + + - name: Build Web App + run: | + cd mnemo_cards_web_v2 + flutter pub get + flutter build web --release --dart-define=API_BASE_URL=https://api.memo-cards.online:8444 --dart2js-optimization=O4 + + - name: Deploy Web App + run: | + # Sync build artifacts + rsync -avz --delete build/web/ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/mnemo_cards/ + + - name: Fix Permissions + run: | + ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "chown -R www-data:www-data /var/www/mnemo_cards && chmod -R 755 /var/www/mnemo_cards" diff --git a/tools/deploy/backend/deploy_remote.sh b/tools/deploy/backend/deploy_remote.sh new file mode 100755 index 0000000..a327735 --- /dev/null +++ b/tools/deploy/backend/deploy_remote.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Script to trigger backend deployment on the remote server +# Usage: ./deploy_remote.sh + +set -e + +# Configuration +SERVER_IP="147.45.152.129" +SERVER_USER="root" +REMOTE_DIR="~/mnemo_cards_backend" +BUILD_SCRIPT="./build_app.sh" + +# Colors +GREEN='\033[0;32m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}[INFO]${NC} Starting backend deployment on ${SERVER_USER}@${SERVER_IP}..." + +# Sync source code +echo -e "${BLUE}[INFO]${NC} Syncing source code to ${SERVER_USER}@${SERVER_IP}..." + +# Sync common packages first +rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'doc' \ + mnemo_cards_common \ + mnemo_cards_common_backend \ + "${SERVER_USER}@${SERVER_IP}:~/" + +# Sync backend project +rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'server.exe' \ + mnemo_cards_backend \ + "${SERVER_USER}@${SERVER_IP}:~/" + +# Sync build script +rsync -avz tools/deploy/backend/server_build.sh "${SERVER_USER}@${SERVER_IP}:~/mnemo_cards_backend/" +ssh "${SERVER_USER}@${SERVER_IP}" "chmod +x ~/mnemo_cards_backend/server_build.sh" + +echo -e "${BLUE}[INFO]${NC} Triggering remote build..." + +# Execute remote build script +ssh -t "${SERVER_USER}@${SERVER_IP}" "~/mnemo_cards_backend/server_build.sh" + +echo -e "${GREEN}[SUCCESS]${NC} Backend deployment triggered successfully!" diff --git a/tools/deploy/backend/server_build.sh b/tools/deploy/backend/server_build.sh new file mode 100644 index 0000000..7e96dc9 --- /dev/null +++ b/tools/deploy/backend/server_build.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Script to build backend on the server +# This script assumes source code is already present (synced via rsync) +# Usage: ./server_build.sh + +set -e -v + +# Go to backend directory +cd ~/mnemo_cards_backend + +# Get dependencies and compile +echo "📦 Getting dependencies..." +dart pub get + +echo "🔨 Compiling server..." +dart compile exe --verbose lib/main.dart -o server_build.exe + +# Stop service +echo "🛑 Stopping service..." +sudo systemctl stop mnemo_cards_server || true + +# Update service file +echo "⚙️ Updating service configuration..." +sudo chmod 777 mnemo_cards_server.service +sudo cp mnemo_cards_server.service /etc/systemd/system/ + +# Update executable +echo "🔄 Replacing executable..." +sudo cp server_build.exe server.exe +rm server_build.exe + +# Check certificates and configure mode +if [ -d "/etc/letsencrypt/live/api.memo-cards.online" ]; then + echo "✅ Let's Encrypt certificates found. Configuring dual mode..." + sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe --dual --certs /etc/letsencrypt/live/api.memo-cards.online -a 0.0.0.0 -p 8443|' /etc/systemd/system/mnemo_cards_server.service +else + echo "⚠️ No certificates found. Configuring HTTP mode..." + sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe -a 0.0.0.0 -p 8443|' /etc/systemd/system/mnemo_cards_server.service +fi + +# Reload and restart +echo "🚀 Restarting service..." +sudo systemctl daemon-reload +sudo systemctl start mnemo_cards_server + +# Check status +sleep 2 +systemctl status mnemo_cards_server --no-pager diff --git a/tools/deploy/fix-git-permissions.sh b/tools/deploy/fix-git-permissions.sh new file mode 100755 index 0000000..9acbd01 --- /dev/null +++ b/tools/deploy/fix-git-permissions.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# Script to fix git repository permissions +# Fixes "insufficient permission for adding an object" error + +set -e + +SERVER_IP="147.45.152.129" +SERVER_USER="root" +REPO_PATH="/home/vscode/cards" + +echo "🔧 Fixing git repository permissions on server..." + +ssh "$SERVER_USER@$SERVER_IP" << 'EOF' + set -e + + REPO_PATH="/home/vscode/cards" + VSCODE_USER="vscode" + + echo "📝 Checking current ownership..." + echo "Current ownership of $REPO_PATH:" + ls -la "$REPO_PATH" | head -10 + + echo "" + echo "🔄 Fixing ownership and permissions..." + + # Change ownership of entire repository to vscode user + chown -R $VSCODE_USER:$VSCODE_USER "$REPO_PATH" + + # Fix permissions + # Directories: rwxr-xr-x (755) + find "$REPO_PATH" -type d -exec chmod 755 {} \; + + # Files: rw-r--r-- (644) + find "$REPO_PATH" -type f -exec chmod 644 {} \; + + # Make scripts executable + find "$REPO_PATH" -type f -name "*.sh" -exec chmod 755 {} \; + + # Fix .git directory specifically + if [ -d "$REPO_PATH/.git" ]; then + echo "🔐 Fixing .git directory permissions..." + chown -R $VSCODE_USER:$VSCODE_USER "$REPO_PATH/.git" + chmod -R u+rwX "$REPO_PATH/.git" + fi + + # Fix all submodules + echo "📦 Fixing submodules if any..." + find "$REPO_PATH" -name ".git" -type d | while read gitdir; do + echo " Fixing: $gitdir" + chown -R $VSCODE_USER:$VSCODE_USER "$gitdir" + chmod -R u+rwX "$gitdir" + done + + # Fix common subdirectories + for subdir in mnemo_cards_common mnemo_cards_backend mnemo_cards_web_v2 mnemo_cards_frontend_common; do + if [ -d "$REPO_PATH/$subdir" ]; then + echo " Fixing: $REPO_PATH/$subdir" + chown -R $VSCODE_USER:$VSCODE_USER "$REPO_PATH/$subdir" + if [ -d "$REPO_PATH/$subdir/.git" ]; then + chmod -R u+rwX "$REPO_PATH/$subdir/.git" + fi + fi + done + + echo "" + echo "✅ Permissions fixed!" + echo "" + echo "📊 New ownership:" + ls -la "$REPO_PATH" | head -10 + + echo "" + echo "🧪 Testing git status..." + cd "$REPO_PATH/mnemo_cards_common" + sudo -u $VSCODE_USER git status || echo "Git status check completed" + +EOF + +echo "" +echo "✅ Done! Git operations should now work without permission errors." +echo "💡 Try running your deployment script again." + diff --git a/tools/deploy/fix-nginx-upload-limit.sh b/tools/deploy/fix-nginx-upload-limit.sh new file mode 100755 index 0000000..8b79fd1 --- /dev/null +++ b/tools/deploy/fix-nginx-upload-limit.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Script to fix nginx 413 error by increasing client_max_body_size +# This script updates nginx configuration on the server for all domains +# including Forgejo (git push), VSCode, and web apps + +set -e + +SERVER_IP="147.45.152.129" +SERVER_USER="root" +MAX_SIZE="100M" + +echo "🔧 Fixing nginx upload limit (413 error) on server..." + +ssh "$SERVER_USER@$SERVER_IP" << 'EOF' + set -e + + echo "📝 Checking current nginx configurations..." + + # Update global nginx config + if ! grep -q "client_max_body_size" /etc/nginx/nginx.conf; then + echo "Adding client_max_body_size to global nginx config..." + sed -i '/http {/a\ client_max_body_size 100M;' /etc/nginx/nginx.conf + else + echo "Updating existing client_max_body_size in global config..." + sed -i 's/client_max_body_size.*$/client_max_body_size 100M;/' /etc/nginx/nginx.conf + fi + + # Update all site configs in sites-available + echo "Updating all site configurations..." + for conf in /etc/nginx/sites-available/*; do + if [ -f "$conf" ]; then + echo "Processing: $conf" + + # Remove all existing client_max_body_size lines to avoid duplicates + sed -i '/client_max_body_size/d' "$conf" + + # Add client_max_body_size once in each server block (after first server_name) + # Use awk to add only once per server block + awk ' + /server \{/ { in_server=1; added=0 } + /\}/ && in_server { in_server=0 } + { print } + /server_name/ && in_server && !added { + print " client_max_body_size 100M;" + added=1 + } + ' "$conf" > "$conf.tmp" && mv "$conf.tmp" "$conf" + fi + done + + echo "🧪 Testing nginx configuration..." + /usr/sbin/nginx -t + + if [ $? -eq 0 ]; then + echo "✅ Nginx configuration is valid" + echo "🔄 Reloading nginx..." + /usr/bin/systemctl reload nginx + echo "✅ Nginx reloaded successfully" + + echo "" + echo "📊 Summary:" + echo " - client_max_body_size set to 100M globally" + echo " - All site configurations updated" + echo " - Git push should now work without 413 errors" + echo "" + echo "Current client_max_body_size in configs:" + grep -r "client_max_body_size" /etc/nginx/ 2>/dev/null | grep -v ".default" || echo " (checking...)" + else + echo "❌ Nginx configuration test failed" + exit 1 + fi +EOF + +echo "" +echo "✅ Done! Git push should now work without 413 errors." +echo "💡 If you still get 413, try increasing MAX_SIZE in this script."