🚀 Obsidian синхронизация бесплатно: Полное руководство по настройке автоматической синхронизации через GitHub
Введение для LINUX. Windows 11 ниже.
Obsidian синхронизация бесплатно— это реальность! В этом подробном руководстве мы покажем, как настроить полноценную систему автоматической синхронизации заметок Obsidian между устройствами без платной подписки Obsidian Sync. Используя GitHub и простые скрипты, вы получите надежнуюбесплатную синхронизацию Obsidian с автоматическими резервными копиями.
Что вы получите:
-
✅ Автоматическая синхронизация каждые 15 минут
-
✅ Графическое меню управления с уведомлениями
-
✅ Подробное логирование всех операций
-
✅ Резервное копирование в облаке GitHub
-
✅ Мониторинг статуса и статистика
-
✅ Принудительная синхронизация при необходимости
Требования к системе
Операционная система
-
Linux (Ubuntu, Debian, Zorin OS, Linux Mint)
-
macOS (с небольшими модификациями)
-
Windows (через WSL)
Необходимые пакеты
# Основные пакеты для синхронизации
sudo apt update
sudo apt install -y git curl wget nano cron
# Пакеты для графического интерфейса
sudo apt install -y zenity notify-send libnotify-bin
# Дополнительные утилиты
sudo apt install -y tree htop
Подготовка GitHub репозитория
Создание репозитория
-
Войдите в GitHub и создайте новый приватный репозиторий
-
Название:
obsidian-notes(или любое другое) -
Описание: “Личные заметки Obsidian”
-
Приватность: Private (для конфиденциальности)
Настройка SSH ключей
# Генерируем SSH ключ для GitHub
ssh-keygen -t ed25519 -C "your-email@example.com" -f ~/.ssh/github_obsidian
# Добавляем ключ в SSH агент
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/github_obsidian
# Выводим публичный ключ для добавления в GitHub
cat ~/.ssh/github_obsidian.pub
Скопируйте вывод команды и добавьте SSH ключ в GitHub:
-
Перейдите в Settings → SSH and GPG keys → New SSH key
-
Вставьте скопированный ключ
Настройка SSH конфигурации
# Создаем конфигурацию SSH
nano ~/.ssh/config
Содержимое файла:
Host github-obsidian
HostName github.com
User git
IdentityFile ~/.ssh/github_obsidian
IdentitiesOnly yes
Инициализация Obsidian хранилища
Подготовка папки с заметками
# Переходим в папку с заметками Obsidian
cd "$HOME/Документы/Obsidian Vault"
# Инициализируем Git репозиторий
git init
# Настраиваем Git пользователя
git config user.name "Ваше Имя"
git config user.email "your-email@example.com"
# Создаем .gitignore для исключения служебных файлов
nano .gitignore
Содержимое .gitignore:
# Obsidian служебные файлы
.obsidian/workspace*
.obsidian/hotkeys.json
.obsidian/appearance.json
.obsidian/graph.json
# Системные файлы
.DS_Store
Thumbs.db
*.tmp
*.temp
# Конфликтные файлы
*conflict*
Первоначальная настройка репозитория
# Добавляем удаленный репозиторий
git remote add origin git@github-obsidian:ваш-username/obsidian-notes.git
# Создаем первый коммит
git add .
git commit -m "Initial commit: Obsidian vault setup"
# Отправляем в GitHub
git branch -M main
git push -u origin main
Создание системы автоматической синхронизации
Структура проекта
# Создаем папку для скриптов
mkdir -p ~/scripts/obsidian-sync
cd ~/scripts/obsidian-sync
# Создаем структуру файлов
touch obsidian-sync.sh
touch force-sync.sh
touch status.sh
touch quick-menu.sh
touch advanced-menu.sh
touch sync.log
Основной скрипт синхронизации
nano ~/scripts/obsidian-sync/obsidian-sync.sh
Полный код скрипта:
#!/bin/bash
# Obsidian Auto-Sync Script
# Автоматическая синхронизация заметок с GitHub
# Конфигурация
OBSIDIAN_PATH="$HOME/Документы/Obsidian Vault"
LOG_FILE="$HOME/scripts/obsidian-sync/sync.log"
HOSTNAME=$(hostname)
# Функция логирования
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Функция уведомлений
notify() {
local message="$1"
local icon="$2"
# Desktop уведомление
if command -v notify-send >/dev/null 2>&1; then
notify-send "Obsidian Sync" "$message" --icon="$icon" --expire-time=5000
fi
# Лог уведомление
log "NOTIFICATION: $message"
}
# Проверка существования папки
if [ ! -d "$OBSIDIAN_PATH" ]; then
log "ERROR: Папка Obsidian не найдена: $OBSIDIAN_PATH"
exit 1
fi
cd "$OBSIDIAN_PATH"
log "=== Начало синхронизации ==="
# Проверяем статус Git
if [ ! -d ".git" ]; then
log "ERROR: Git репозиторий не инициализирован"
exit 1
fi
# Получаем изменения с сервера
log "Получаем изменения с GitHub..."
git fetch origin main 2>&1 | tee -a "$LOG_FILE"
# Проверяем конфликты
REMOTE_CHANGES=$(git rev-list HEAD..origin/main --count 2>/dev/null || echo "0")
LOCAL_CHANGES=$(git status --porcelain | wc -l)
log "Удаленных изменений: $REMOTE_CHANGES, локальных: $LOCAL_CHANGES"
# Если есть удаленные изменения, сливаем их
if [ "$REMOTE_CHANGES" -gt 0 ]; then
log "Применяем удаленные изменения..."
git pull origin main 2>&1 | tee -a "$LOG_FILE"
if [ $? -eq 0 ]; then
notify "📥 Получено $REMOTE_CHANGES изменений с сервера" "dialog-information"
else
log "ERROR: Ошибка при получении изменений"
notify "❌ Ошибка синхронизации" "dialog-error"
exit 1
fi
fi
# Если есть локальные изменения, отправляем их
if [ "$LOCAL_CHANGES" -gt 0 ]; then
log "Сохраняем локальные изменения..."
# Добавляем все изменения
git add . 2>&1 | tee -a "$LOG_FILE"
# Создаем коммит с автоматическим сообщением
COMMIT_MSG="Auto-sync from $HOSTNAME: $(date '+%Y-%m-%d %H:%M:%S')"
git commit -m "$COMMIT_MSG" 2>&1 | tee -a "$LOG_FILE"
# Отправляем на сервер
log "Отправляем изменения на сервер..."
git push origin main 2>&1 | tee -a "$LOG_FILE"
if [ $? -eq 0 ]; then
notify "📤 Obsidian Sync - Отправлено $LOCAL_CHANGES изменений" "dialog-information"
else
log "ERROR: Ошибка при отправке изменений"
notify "❌ Ошибка отправки на сервер" "dialog-error"
exit 1
fi
fi
# Если нет изменений
if [ "$REMOTE_CHANGES" -eq 0 ] && [ "$LOCAL_CHANGES" -eq 0 ]; then
log "Изменений нет, синхронизация не требуется"
fi
log "=== Синхронизация завершена ==="
Скрипт принудительной синхронизации
nano ~/scripts/obsidian-sync/force-sync.sh
Код скрипта:
#!/bin/bash
# Force Sync Script - Принудительная синхронизация
# Используется при конфликтах или проблемах
OBSIDIAN_PATH="$HOME/Документы/Obsidian Vault"
LOG_FILE="$HOME/scripts/obsidian-sync/sync.log"
BACKUP_DIR="$HOME/scripts/obsidian-sync/backups"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] FORCE: $1" | tee -a "$LOG_FILE"
}
# Создаем папку для резервных копий
mkdir -p "$BACKUP_DIR"
cd "$OBSIDIAN_PATH"
log "=== Начало принудительной синхронизации ==="
# Создаем резервную копию локальных изменений
BACKUP_NAME="backup-$(date +%Y%m%d-%H%M%S).tar.gz"
tar -czf "$BACKUP_DIR/$BACKUP_NAME" . 2>/dev/null
log "Создана резервная копия: $BACKUP_NAME"
# Сбрасываем локальные изменения
git fetch origin main
git reset --hard origin/main
git clean -fd
log "Локальные изменения сброшены до состояния сервера"
# Запускаем обычную синхронизацию
~/scripts/obsidian-sync/obsidian-sync.sh
log "=== Принудительная синхронизация завершена ==="
Скрипт мониторинга статуса
nano ~/scripts/obsidian-sync/status.sh
Код скрипта:
#!/bin/bash
# Status Monitor Script - Мониторинг состояния системы
OBSIDIAN_PATH="$HOME/Документы/Obsidian Vault"
LOG_FILE="$HOME/scripts/obsidian-sync/sync.log"
cd "$OBSIDIAN_PATH"
echo "🔍 СТАТУС OBSIDIAN SYNC"
echo "========================"
echo "📅 Время: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
# Git статус
echo "📊 Git статус:"
git status --short
echo ""
echo "📈 Статистика файлов:"
echo " Всего .md файлов: $(find . -name "*.md" | wc -l)"
echo " Всего папок: $(find . -type d | wc -l)"
echo " Размер хранилища: $(du -sh . | cut -f1)"
echo " Последний коммит: $(git log -1 --format='%h - %s (%cr)' 2>/dev/null || echo 'Нет коммитов')"
echo ""
echo "🔄 Удаленные изменения:"
git fetch origin >/dev/null 2>&1
REMOTE_CHANGES=$(git rev-list HEAD..origin/main --count 2>/dev/null || echo "0")
LOCAL_CHANGES=$(git status --porcelain | wc -l)
if [ "$REMOTE_CHANGES" -gt 0 ]; then
echo " ⚠️ Есть $REMOTE_CHANGES изменений на сервере"
elif [ "$LOCAL_CHANGES" -gt 0 ]; then
echo " 📝 Есть $LOCAL_CHANGES локальных изменений"
else
echo " ✅ Полностью синхронизировано"
fi
echo ""
echo "📝 Последние записи лога:"
if [ -f "$LOG_FILE" ]; then
tail -5 "$LOG_FILE" | sed 's/^/ /'
else
echo " Лог файл не найден"
fi
echo ""
echo "⚙️ Автосинхронизация:"
if crontab -l 2>/dev/null | grep -q "obsidian-sync"; then
echo " ✅ Настроена и активна"
echo " 📅 Расписание: $(crontab -l | grep obsidian-sync | cut -d' ' -f1-5)"
else
echo " ❌ Не настроена"
fi
Графический интерфейс управления
Простое меню управления
nano ~/scripts/obsidian-sync/quick-menu.sh
Код меню:
#!/bin/bash
# Quick Menu - Простое графическое меню
choice=$(zenity --list \
--title="Obsidian Sync - Быстрые действия" \
--text="Выберите действие:" \
--column="Действие" \
--column="Описание" \
"sync" "🔄 Синхронизировать сейчас" \
"status" "📊 Показать статус" \
"force" "⚡ Принудительная синхронизация" \
"log" "📝 Показать лог" \
"open" "📂 Открыть папку Obsidian" \
--width=400 --height=300)
case $choice in
"sync")
~/scripts/obsidian-sync/obsidian-sync.sh
zenity --info --text="Синхронизация завершена!" --title="Obsidian Sync"
;;
"status")
~/scripts/obsidian-sync/status.sh | zenity --text-info \
--title="Статус Obsidian Sync" \
--width=600 --height=400 \
--font="monospace 10"
;;
"force")
if zenity --question --text="⚠️ Выполнить принудительную синхронизацию?\n\nЭто может перезаписать локальные изменения."; then
~/scripts/obsidian-sync/force-sync.sh
zenity --info --text="Принудительная синхронизация завершена!" --title="Obsidian Sync"
fi
;;
"log")
if [ -f "$HOME/scripts/obsidian-sync/sync.log" ]; then
cat "$HOME/scripts/obsidian-sync/sync.log" | zenity --text-info \
--title="Лог Obsidian Sync" \
--width=600 --height=400 \
--font="monospace 10"
else
zenity --info --text="Лог файл не найден." --title="Общая информация"
fi
;;
"open")
xdg-open "$HOME/Документы/Obsidian Vault"
;;
esac
Расписание автоматической синхронизации
# Открываем crontab для редактирования
crontab -e
Добавьте следующую строку для автоматической синхронизации каждые 15 минут:
*/15 * * * * ~/scripts/obsidian-sync/obsidian-sync.sh
Заключение
Теперь у вас есть полноценная система автоматической синхронизации заметок Obsidian с использованием GitHub. Вы можете легко управлять синхронизацией через графический интерфейс, а также получать уведомления о статусе. Не забывайте проверять логи для отслеживания всех операций.
Obsidian синхронизация бесплатно на Windows 11: Полное руководство по настройке автоматической синхронизации через GitHub
Введение
Obsidian синхронизация бесплатно на Windows 11— это доступная альтернатива платной подписке Obsidian Sync! В этом подробном руководстве мы покажем, как настроить полноценную систему автоматической синхронизации заметок Obsidian между устройствами на Windows 11 без дополнительных затрат. Используя GitHub, PowerShell и планировщик задач Windows, вы получите надежнуюбесплатную синхронизацию Obsidian с автоматическими резервными копиями.
Что вы получите:
-
✅ Автоматическая синхронизация каждые 15 минут
-
✅ Графические уведомления Windows о статусе синхронизации
-
✅ PowerShell скрипты для управления
-
✅ Планировщик задач Windows для автоматизации
-
✅ Резервное копирование в облаке GitHub
-
✅ Мониторинг статуса и подробная статистика
-
✅ Графическое меню управления через Windows Forms
Требования к системе
Операционная система
-
Windows 11 (любая редакция)
-
Windows 10 (с обновлениями)
Необходимое программное обеспечение
1. Git для Windows
# Скачайте Git с официального сайта
# https://git-scm.com/download/win
# Или установите через winget
winget install Git.Git
2. PowerShell 7 (рекомендуется)
# Установка через winget
winget install Microsoft.PowerShell
# Или скачайте с GitHub
# https://github.com/PowerShell/PowerShell/releases
3. Windows Terminal (опционально)
# Установка через Microsoft Store или winget
winget install Microsoft.WindowsTerminal
Подготовка рабочей среды
Создание структуры папок
# Открываем PowerShell от имени администратора
# Создаем папку для скриптов
New-Item -ItemType Directory -Path "$env:USERPROFILE\Scripts\ObsidianSync" -Force
# Создаем папку для логов
New-Item -ItemType Directory -Path "$env:USERPROFILE\Scripts\ObsidianSync\Logs" -Force
# Создаем папку для резервных копий
New-Item -ItemType Directory -Path "$env:USERPROFILE\Scripts\ObsidianSync\Backups" -Force
# Переходим в рабочую папку
Set-Location "$env:USERPROFILE\Scripts\ObsidianSync"
Настройка политики выполнения PowerShell
# Разрешаем выполнение локальных скриптов
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Проверяем текущую политику
Get-ExecutionPolicy -List
Подготовка GitHub репозитория
Создание репозитория
-
Войдите в GitHub и создайте новый приватный репозиторий
-
Название:
obsidian-notes-windows -
Описание: “Личные заметки Obsidian - Windows 11”
-
Приватность: Private (для конфиденциальности)
Настройка SSH ключей в Windows
# Проверяем наличие OpenSSH
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
# Устанавливаем OpenSSH Client если нужно
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
# Создаем папку .ssh если её нет
if (!(Test-Path "$env:USERPROFILE\.ssh")) {
New-Item -ItemType Directory -Path "$env:USERPROFILE\.ssh"
}
# Генерируем SSH ключ
ssh-keygen -t ed25519 -C "your-email@example.com" -f "$env:USERPROFILE\.ssh\github_obsidian"
# Запускаем SSH Agent
Start-Service ssh-agent
Set-Service -Name ssh-agent -StartupType Manual
# Добавляем ключ в SSH Agent
ssh-add "$env:USERPROFILE\.ssh\github_obsidian"
# Выводим публичный ключ для GitHub
Get-Content "$env:USERPROFILE\.ssh\github_obsidian.pub"
Настройка SSH конфигурации
# Создаем SSH config файл
@"
Host github-obsidian
HostName github.com
User git
IdentityFile ~/.ssh/github_obsidian
IdentitiesOnly yes
"@ | Out-File -FilePath "$env:USERPROFILE\.ssh\config" -Encoding UTF8
Добавьте SSH ключ в GitHub:
-
Перейдите в Settings → SSH and GPG keys → New SSH key
-
Вставьте содержимое файла
github_obsidian.pub
Инициализация Obsidian хранилища
Подготовка папки с заметками
# Переходим в папку Obsidian (стандартный путь)
$ObsidianPath = "$env:USERPROFILE\Documents\Obsidian Vault"
Set-Location $ObsidianPath
# Инициализируем Git репозиторий
git init
# Настраиваем Git пользователя
git config user.name "Ваше Имя"
git config user.email "your-email@example.com"
# Создаем .gitignore
@"
# Obsidian служебные файлы
.obsidian/workspace*
.obsidian/hotkeys.json
.obsidian/appearance.json
.obsidian/graph.json
.obsidian/plugins/*/data.json
# Windows системные файлы
Thumbs.db
Desktop.ini
*.tmp
*.temp
~$*
# Конфликтные файлы
*conflict*
*.orig
"@ | Out-File -FilePath ".gitignore" -Encoding UTF8
# Добавляем удаленный репозиторий
git remote add origin git@github-obsidian:ваш-username/obsidian-notes-windows.git
# Первый коммит
git add .
git commit -m "Initial commit: Obsidian vault setup on Windows 11"
# Отправляем в GitHub
git branch -M main
git push -u origin main
Создание PowerShell скриптов синхронизации
Основной скрипт синхронизации
# Создаем основной скрипт синхронизации
@'
# ObsidianSync.ps1 - Основной скрипт синхронизации
param(
[switch]$Force,
[switch]$Quiet
)
# Конфигурация
$ObsidianPath = "$env:USERPROFILE\Documents\Obsidian Vault"
$LogPath = "$env:USERPROFILE\Scripts\ObsidianSync\Logs"
$LogFile = "$LogPath\sync-$(Get-Date -Format 'yyyy-MM').log"
$ComputerName = $env:COMPUTERNAME
# Функция логирования
function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogEntry = "[$Timestamp] [$Level] $Message"
# Записываем в лог файл
$LogEntry | Out-File -FilePath $LogFile -Append -Encoding UTF8
# Выводим в консоль если не тихий режим
if (-not $Quiet) {
Write-Host $LogEntry
}
}
# Функция Windows уведомлений
function Show-Notification {
param(
[string]$Title = "Obsidian Sync",
[string]$Message,
[string]$Icon = "Info"
)
# Используем Windows Toast уведомления
Add-Type -AssemblyName System.Windows.Forms
$notification = New-Object System.Windows.Forms.NotifyIcon
$notification.Icon = [System.Drawing.SystemIcons]::Information
$notification.BalloonTipIcon = $Icon
$notification.BalloonTipText = $Message
$notification.BalloonTipTitle = $Title
$notification.Visible = $True
$notification.ShowBalloonTip(5000)
# Логируем уведомление
Write-Log "NOTIFICATION: $Title - $Message"
# Очищаем ресурсы
Start-Sleep -Seconds 1
$notification.Dispose()
}
# Проверка существования папки Obsidian
if (-not (Test-Path $ObsidianPath)) {
Write-Log "ERROR: Папка Obsidian не найдена: $ObsidianPath" "ERROR"
Show-Notification -Message "Папка Obsidian не найдена!" -Icon "Error"
exit 1
}
# Создаем папку логов если её нет
if (-not (Test-Path $LogPath)) {
New-Item -ItemType Directory -Path $LogPath -Force | Out-Null
}
Set-Location $ObsidianPath
Write-Log "=== Начало синхронизации ==="
# Проверяем Git репозиторий
if (-not (Test-Path ".git")) {
Write-Log "ERROR: Git репозиторий не инициализирован" "ERROR"
Show-Notification -Message "Git репозиторий не найден!" -Icon "Error"
exit 1
}
try {
# Получаем изменения с сервера
Write-Log "Получаем изменения с GitHub..."
git fetch origin main 2>&1 | Out-File -FilePath $LogFile -Append -Encoding UTF8
# Проверяем количество изменений
$RemoteChanges = (git rev-list HEAD..origin/main --count 2>$null)
if (-not $RemoteChanges) { $RemoteChanges = 0 }
$LocalChanges = (git status --porcelain | Measure-Object).Count
Write-Log "Удаленных изменений: $RemoteChanges, локальных: $LocalChanges"
# Обрабатываем удаленные изменения
if ([int]$RemoteChanges -gt 0) {
Write-Log "Применяем удаленные изменения..."
$pullResult = git pull origin main 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Log "Успешно получено $RemoteChanges изменений"
Show-Notification -Message "📥 Получено $RemoteChanges изменений с сервера"
} else {
Write-Log "ERROR: Ошибка при получении изменений: $pullResult" "ERROR"
Show-Notification -Message "❌ Ошибка синхронизации" -Icon "Error"
exit 1
}
}
# Обрабатываем локальные изменения
if ($LocalChanges -gt 0) {
Write-Log "Сохраняем локальные изменения..."
# Добавляем все изменения
git add . 2>&1 | Out-File -FilePath $LogFile -Append -Encoding UTF8
# Создаем коммит
$CommitMessage = "Auto-sync from $ComputerName`: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
git commit -m $CommitMessage 2>&1 | Out-File -FilePath $LogFile -Append -Encoding UTF8
# Отправляем на сервер
Write-Log "Отправляем изменения на сервер..."
$pushResult = git push origin main 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Log "Успешно отправлено $LocalChanges изменений"
Show-Notification -Message "📤 Отправлено $LocalChanges изменений на сервер"
} else {
Write-Log "ERROR: Ошибка при отправке: $pushResult" "ERROR"
Show-Notification -Message "❌ Ошибка отправки на сервер" -Icon "Error"
exit 1
}
}
# Если нет изменений
if ([int]$RemoteChanges -eq 0 -and $LocalChanges -eq 0) {
Write-Log "Изменений нет, синхронизация не требуется"
if (-not $Quiet) {
Show-Notification -Message "✅ Все синхронизировано"
}
}
} catch {
Write-Log "ERROR: Критическая ошибка: $($_.Exception.Message)" "ERROR"
Show-Notification -Message "❌ Критическая ошибка синхронизации" -Icon "Error"
exit 1
}
Write-Log "=== Синхронизация завершена ==="
'@ | Out-File -FilePath "$env:USERPROFILE\Scripts\ObsidianSync\ObsidianSync.ps1" -Encoding UTF8
Скрипт принудительной синхронизации
# ForceSync.ps1 - Принудительная синхронизация
param([switch]$Confirm)
$ObsidianPath = "$env:USERPROFILE\Documents\Obsidian Vault" $BackupPath = "$env:USERPROFILE\Scripts\ObsidianSync\Backups" $LogFile = "$env:USERPROFILE\Scripts\ObsidianSync\Logs\force-sync-$(Get-Date -Format 'yyyy-MM-dd').log"
function Write-Log { param([string]$Message) $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "[$Timestamp] FORCE: $Message" | Out-File -FilePath $LogFile -Append -Encoding UTF8 Write-Host "[$Timestamp] FORCE: $Message" }
if (-not $Confirm) { $response = Read-Host "⚠️ ВНИМАНИЕ: Принудительная синхронизация сбросит локальные изменения!`nПродолжить? (y/N)" if ($response -ne 'y' -and $response -ne 'Y') { Write-Host "Операция отменена." exit 0 } }
Set-Location $ObsidianPath Write-Log "=== Начало принудительной синхронизации ==="
# Создаем резервную копию
$BackupName = "backup-$(Get-Date -Format 'yyyyMMdd-HHmmss').zip" $BackupFullPath = "$BackupPath\$BackupName"
---
> **Ищете надежного партнера по веб-разработке и автоматизации?**
> Мы помогаем бизнесу расти с помощью современных технологий, автоматизации процессов и экспертного SEO. [Свяжитесь с нами](https://automata.sale/contacts/), чтобы обсудить вашу задачу.
---
**Automata может помочь:**
- [Миграция сайта на современный стек без потери SEO](/automata-site/)
- [Тарифы поддержки и разработки](/tariffs/) Работаю удалённо — цены и условия для вашего города: