Встановлення SurrealDB на VPS: Docker, TLS, persistent storage та автоматичні бекапи
TL;DR
У цьому посібнику ми розгорнемо SurrealDB 2.x на Ubuntu Server 24.04 через Docker Compose, підключимо постійне сховище, закриємо базу за Caddy з автоматичним TLS, налаштуємо firewall і щоденні бекапи в S3 за допомогою Restic.
- SurrealDB працюватиме в окремому контейнері з фіксованою версією образу.
- Дані зберігатимуться на диску VPS, а не всередині ефемерного Docker-контейнера.
- Публічним залишиться лише HTTPS-порт 443; порт SurrealDB 8000 буде доступний лише локально.
- Caddy автоматично отримає та продовжить TLS-сертифікат Let’s Encrypt.
- Щодня створюватимуться логічний експорт бази та резервна копія конфігурації.
- Перед оновленням можна виконати перевірку, ручний експорт і відкат контейнера до попередньої версії.
1. TL;DR
Цей розділ уже містить короткий план розгортання. Якщо ви вперше працюєте з VPS, виконуйте команди послідовно: спочатку підготуйте операційну систему, потім встановіть Docker, створіть каталог проєкту, налаштуйте змінні середовища, запустіть контейнери й лише після перевірки підключайте DNS до сервера.
2. Зміст
Стаття розрахована на власника VPS, який хоче самостійно запустити SurrealDB для SaaS-застосунку, внутрішнього сервісу, прототипу або невеликого production-проєкту. Конфігурація не прив’язана до конкретного фреймворку: до бази можна підключатися через HTTP API, WebSocket або офіційний SDK.
Для production важливо розуміти межі прикладу. Один VPS з однією копією бази не є відмовостійким кластером. TLS, firewall і бекапи захищають від поширених операційних помилок, але не замінюють резервний сервер, моніторинг і регулярну перевірку відновлення даних.
3. Що ми налаштовуємо і навіщо
Що таке SurrealDB
SurrealDB — мультимодельна база даних із підтримкою документного, графового та реляційного підходів. Вона надає власну SQL-подібну мову SurrealQL, HTTP API, WebSocket-підключення та механізм автентифікації. Це зручно, коли застосунку потрібні документи, зв’язки між сутностями та запити до кількох моделей даних без окремого набору спеціалізованих сервісів.
У посібнику використовується гілка SurrealDB 2.x. Конкретний тег образу потрібно фіксувати, а не використовувати latest. Непередбачуване оновлення може змінити синтаксис запитів, формат експорту або поведінку транзакцій у момент перезапуску контейнера.
Архітектура підсумкового встановлення
На сервері працюватимуть два контейнери Docker Compose:
surrealdb— сервер бази даних, що слухає HTTP і WebSocket на внутрішній адресі Docker-мережі;caddy— reverse proxy, що приймає HTTPS-запити та передає їх до SurrealDB.
Порт 8000 не буде опублікований у зовнішній інтернет. Caddy підключиться до SurrealDB за іменем сервісу surrealdb:8000. Дані бази буде розміщено в каталозі /srv/surrealdb/data, який монтується в контейнер. Конфігурація Compose, файл .env, Caddyfile та експорт бази зберігатимуться окремо від Docker-шарів.
Що ви отримаєте після виконання інструкції
Після налаштування у вас буде адреса на кшталт https://db.example.com. Через неї застосунок зможе виконувати API-запити до SurrealDB. Сервер автоматично отримає TLS-сертифікат, а Caddy продовжуватиме його без ручного запуску Certbot.
Також з’явиться команда для ручної перевірки:
curl -fsS https://db.example.com/health
За справної роботи SurrealDB відповість успішним HTTP-статусом. Для адміністративних операцій потрібно використовувати окремі облікові дані й не передавати пароль в URL, shell history або вихідний код застосунку.
Self-hosted чи managed-сервіс
| Критерій | SurrealDB на власному VPS | Managed-сервіс |
|---|---|---|
| Контроль | Повний контроль над ОС, мережею, версіями та розміщенням даних | Частина інфраструктури прихована й керується провайдером |
| Вартість | Фіксована вартість VPS та окремого сховища бекапів | Оплата залежить від тарифу, операцій, трафіку та обсягу даних |
| Обслуговування | Оновлення, моніторинг і відновлення виконуються самостійно | Частину завдань виконує оператор сервісу |
| Гнучкість | Можна змінювати мережеві правила, проксі та файлову структуру | Доступні лише передбачені API та налаштування |
Self-hosted варіант доцільний, якщо дані мають зберігатися на вибраному майданчику, потрібен передбачуваний бюджет або необхідний повний контроль над оточенням. Managed-рішення може бути кращим для команди без досвіду адміністрування, для критичних систем із вимогами високої доступності або коли немає часу самостійно тестувати відновлення.
Обмеження одиночного сервера
Один VPS має єдину точку відмови: проблема з диском, гіпервізором, мережевим з’єднанням або помилкова команда адміністратора може тимчасово зробити базу недоступною. Бекап у тому самому каталозі не врятує від втрати всього сервера, тому резервні копії потрібно надсилати до зовнішнього S3-сумісного сховища або на окремий сервер.
Не публікуйте SurrealDB безпосередньо в інтернет без TLS і мережевих обмежень. Навіть за наявності вбудованої автентифікації відкритий порт збільшує поверхню атаки та ускладнює контроль доступу.
4. Який VPS-конфіг потрібен для цього завдання
Мінімальна конфігурація
Для розробки, тестування та невеликої бази підійде VPS із двома віртуальними CPU, 4 ГБ RAM і швидким SSD-диском обсягом від 40 ГБ. Для production потрібно залишити запас для файлового кешу, Docker, reverse proxy, бекапів і фонових процесів застосунку.
| Сценарій | CPU | RAM | Диск | Мережа |
|---|---|---|---|---|
| Локальна розробка та демо | 2 vCPU | 2–4 ГБ | 40 ГБ NVMe SSD | 100 Мбіт/с |
| Невеликий production | 2–4 vCPU | 4–8 ГБ | 80–160 ГБ NVMe SSD | 100–1000 Мбіт/с |
| Середнє навантаження | 4–8 vCPU | 16–32 ГБ | 200+ ГБ NVMe SSD | 1 Гбіт/с |
Як практичний стартовий варіант можна взяти VPS із 4 vCPU, 8 ГБ RAM, NVMe SSD від 100 ГБ, публічною IPv4-адресою та портом 1 Гбіт/с. Такий запас дасть змогу запустити саму базу, Caddy, невеликий backend і сервіс моніторингу, не доводячи використання пам’яті до межі.
Як оцінити диск
Розмір диска має враховувати не лише поточний обсяг даних. Залиште щонайменше 30–40 відсотків вільного простору для тимчасових файлів, фрагментації, оновлень та експорту. Наприклад, якщо база займає 35 ГБ, диск на 40 ГБ замалий: експорт, лог і нові записи можуть швидко заповнити файлову систему.
Логічний експорт може тимчасово займати обсяг, співмірний із базою. Якщо планується зберігати кілька локальних копій, розмір диска потрібно збільшити або одразу надсилати кожну копію до зовнішнього сховища.
Коли потрібен dedicated
Виділений сервер має сенс, якщо база постійно використовує багато CPU або RAM, працює з десятками й сотнями гігабайтів даних, обслуговує великий потік запитів або повинна мати передбачувану продуктивність без впливу сусідніх віртуальних машин. Dedicated також зручний для великої ноди, аналітики та кількох сервісів, які не можна розділити між різними VPS.
Для однієї невеликої SurrealDB dedicated зазвичай надлишковий. Спочатку виміряйте фактичне навантаження: середнє та пікове використання CPU, затримку диска, кількість з’єднань, розмір бази та частоту запитів. Перехід на dedicated без метрик часто лише збільшує витрати, але не усуває неправильні індекси або повільні запити.
Вибір локації
Розміщуйте VPS ближче до користувачів і застосунку. Якщо backend і SurrealDB знаходяться в одній локації, затримка між ними буде нижчою, ніж під час підключення через кілька регіонів. Для персональних даних додатково враховуйте вимоги законодавства, договори із замовниками та правила зберігання даних.
Перевірте, чи видає провайдер публічну IPv4 або лише IPv6. Для автоматичного TLS домен має вказувати на сервер, а вхідні TCP-порти 80 і 443 повинні бути доступні з інтернету. Якщо використовується лише IPv6, переконайтеся, що клієнти справді підтримують такий маршрут.
5. Підготовка сервера
Вихідні умови
Приклад розрахований на свіжу Ubuntu Server 24.04 LTS із користувачем, який має тимчасовий доступ через SSH. Працюйте під звичайним користувачем із sudo, а не під root. Замініть admin, IP-адресу та домен на власні значення.
На локальному комп’ютері створіть ключ, якщо його ще немає:
ssh-keygen -t ed25519 -C "admin@vps"
Передайте публічний ключ на сервер:
ssh-copy-id admin@SERVER_IP
Перевірте вхід за ключем у новому терміналі. Не закривайте поточну SSH-сесію, доки не переконаєтеся, що новий спосіб входу працює.
Оновлення та базові пакети
Підключіться до сервера та оновіть індекс пакетів:
sudo apt update
sudo apt full-upgrade -y
Встановіть утиліти для діагностики, firewall, захисту SSH і роботи з репозиторіями:
sudo apt install -y \
ca-certificates \
curl \
gnupg \
lsb-release \
git \
jq \
unzip \
htop \
ncdu \
ufw \
fail2ban \
restic
Перезавантажте сервер, якщо оновлювалося ядро:
sudo reboot
Користувач і sudo
Якщо користувача ще не створено, виконайте команду під root або наявним адміністратором:
sudo adduser deploy
sudo usermod -aG sudo deploy
sudo install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
sudo cp /home/admin/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys
sudo chown deploy:deploy /home/deploy/.ssh/authorized_keys
sudo chmod 600 /home/deploy/.ssh/authorized_keys
Перевірте вхід:
ssh deploy@SERVER_IP
Налаштування SSH
Створіть окремий drop-in-файл SSH, щоб не змінювати основний конфіг:
sudo tee /etc/ssh/sshd_config.d/ hardening.conf >/dev/null <<'EOF'
В імені шляху вище не повинно бути пробілу. Використовуйте коректну команду:
sudo tee /etc/ssh/sshd_config.d/hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF
sudo sshd -t
sudo systemctl reload ssh
Перш ніж вимикати паролі, переконайтеся, що вхід за ключем уже перевірено. Якщо втратити єдиний робочий ключ і вимкнути пароль, знадобиться консоль провайдера або rescue-режим.
Firewall UFW
Залиште SSH, HTTP і HTTPS. Порт 8000 не відкривайте: він знадобиться лише всередині Docker-мережі.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Якщо SSH працює на нестандартному порту, замініть правило 22/tcp на фактичний порт. У разі використання IPv6 перевірте, що правила UFW застосовуються також до IPv6.
Fail2ban
Створіть локальне налаштування jail для SSH:
sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null <<'EOF'
[sshd]
enabled = true
port = 22
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
Fail2ban не замінює ключі, firewall та оновлення. Він лише тимчасово блокує IP-адреси, з яких спостерігаються повторні невдалі спроби входу.
6. Встановлення ПЗ — покроково
Крок 1. Встановлення Docker Engine і Compose Plugin
Для Ubuntu можна використати офіційний інсталяційний скрипт Docker. У production бажано підключити офіційний apt-репозиторій і зафіксувати версії пакетів, але для першого розгортання скрипт зменшує кількість ручних дій.
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
sudo sh /tmp/get-docker.sh
rm /tmp/get-docker.sh
Додайте поточного користувача до групи Docker:
sudo usermod -aG docker "$USER"
newgrp docker
Перевірте версії:
docker --version
docker compose version
docker run --rm hello-world
У 2026 році використовуйте актуальні Docker Engine і Compose v2, але для відтворюваності фіксуйте версію образу SurrealDB у Compose-файлі. Група Docker фактично надає права, близькі до root, тому не додавайте до неї зайвих користувачів.
Крок 2. Створення структури каталогів
Створіть окремий каталог застосунку, каталог даних і директорію для локальних експортів:
sudo mkdir -p /srv/surrealdb/{data,backups,caddy/data,caddy/config}
sudo chown -R "$USER":"$USER" /srv/surrealdb
cd /srv/surrealdb
Не видаляйте каталог data під час перевстановлення контейнерів. Саме там містяться постійні дані SurrealDB.
Крок 3. Створення файлу секретів
Файл .env буде прочитаний Docker Compose. Пароль має бути довгим, випадковим і унікальним для цієї бази. Не додавайте файл до Git.
DB_ROOT_PASSWORD="$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9_@%+=' | head -c 32)"
printf 'SURREAL_ROOT_USER=root\nSURREAL_ROOT_PASSWORD=%s\n' "$DB_ROOT_PASSWORD" > /srv/surrealdb/.env
chmod 600 /srv/surrealdb/.env
cat /srv/surrealdb/.env
Збережіть пароль у менеджері секретів. Команду cat наведено лише для первинної перевірки, і її не слід виконувати під час запису термінала або демонстрації екрана.
Крок 4. Створення Docker Compose
Нижче використовується приклад образу surrealdb/surrealdb:v2.6.0. Перед встановленням перевірте доступність потрібного стабільного тега в реєстрі та виберіть версію, протестовану вашим застосунком. Не замінюйте тег на latest.
cat > /srv/surrealdb/compose.yml <<'EOF'
services:
surrealdb:
image: surrealdb/surrealdb:v2.6.0
container_name: surrealdb
restart: unless-stopped
command:
- start
- --log
- info
- --user
- ${SURREAL_ROOT_USER}
- --pass
- ${SURREAL_ROOT_PASSWORD}
- rocksdb:/data/database.db
environment:
TZ: UTC
volumes:
- ./data:/data
expose:
- "8000"
healthcheck:
test: ["CMD", "/surreal", "isready", "--endpoint", "http://127.0.0.1:8000"]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
networks:
- surrealnet
caddy:
image: caddy:2.10-alpine
container_name: surrealdb-caddy
restart: unless-stopped
depends_on:
surrealdb:
condition: service_healthy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy/data:/data
- ./caddy/config:/config
networks:
- surrealnet
networks:
surrealnet:
driver: bridge
EOF
Команда start запускає сервер, а шлях rocksdb:/data/database.db вказує SurrealDB використовувати файл RocksDB усередині постійного каталогу. Не монтуйте один і той самий файл одночасно в кілька екземплярів бази.
Крок 5. Запуск і перевірка контейнерів
Перед запуском перевірте підсумкову інтерполяцію змінних і синтаксис Compose:
cd /srv/surrealdb
docker compose --env-file .env config
Запустіть сервіси у фоновому режимі:
docker compose --env-file .env up -d surrealdb
Перегляньте стан і журнали:
docker compose ps
docker compose logs --tail=100 surrealdb
На цьому етапі Caddy ще не налаштований, тому спочатку перевірте внутрішній endpoint:
curl -fsS http://127.0.0.1:8000/health || true
docker inspect --format='{{json .State.Health}}' surrealdb | jq
Якщо контейнер завершив роботу, не запускайте його нескінченно в циклі. Спочатку вивчіть журнали: найчастіше причинами є неправильна змінна середовища, зайнятий порт, пошкоджений каталог даних або помилка в параметрах запуску.
Крок 6. Перевірка версії образу
Переконайтеся, що контейнер працює на очікуваному образі:
docker inspect --format='{{.Config.Image}}' surrealdb
docker exec surrealdb /surreal version
У production запишіть вибраний тег до журналу змін проєкту. Якщо застосунок залежить від конкретних можливостей SurrealQL, створіть тестовий сценарій міграції та запитів до оновлення.
7. Конфігурація
DNS і доменне ім’я
Нехай база буде доступна за адресою db.example.com. Створіть DNS-запис типу A, що вказує на IPv4-адресу VPS. Якщо використовуєте IPv6, додайте AAAA-запис лише після перевірки маршрутизації та firewall.
Перевірити DNS можна безпосередньо із сервера:
getent hosts db.example.com
dig +short A db.example.com
dig +short AAAA db.example.com
Не запускайте автоматичний TLS, доки DNS не почне повертати правильну адресу. Let’s Encrypt має мати можливість підключитися до порту 80 або 443 ззовні.
Caddyfile для TLS і reverse proxy
Створіть файл /srv/surrealdb/Caddyfile. Замініть домен і контактний email на власні значення:
cat > /srv/surrealdb/Caddyfile <<'EOF'
{
email [email protected]
}
db.example.com {
encode zstd gzip
reverse_proxy surrealdb:8000 {
health_uri /health
health_interval 30s
health_timeout 5s
}
log {
output file /data/access.log
format json
}
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
Referrer-Policy "no-referrer"
}
}
EOF
chmod 644 /srv/surrealdb/Caddyfile
Caddy отримує сертифікат, зберігає його в каталозі caddy/data і автоматично подовжує. Цей каталог також потрібно включати до резервних копій: без нього Caddy зможе отримати сертифікат повторно, але буде втрачено локальні дані про стан ACME та історію конфігурації.
Запуск Caddy
Після налаштування DNS запустіть reverse proxy:
cd /srv/surrealdb
docker compose --env-file .env up -d
docker compose ps
docker compose logs --tail=100 caddy
У журналах має бути повідомлення про успішну видачу сертифіката або про те, що сертифікат уже існує. Якщо Caddy не може отримати сертифікат, перевірте DNS, UFW, security group у провайдера та наявність іншого процесу на портах 80 або 443.
Перевірка HTTPS
Перевірте TLS і health endpoint:
curl -I https://db.example.com
curl -fsS https://db.example.com/health
openssl s_client -connect db.example.com:443 -servername db.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
Очікуйте HTTP-відповідь без помилки сертифіката та дати чинності сертифіката, що відповідають поточному періоду. Виконуйте перевірку із зовнішнього комп’ютера, а не лише з самого VPS: локальна перевірка може не виявити проблем із маршрутизацією або DNS.
Перевірка автентифікації
Для адміністративного API використовуйте пароль із локального файлу секретів. Не передавайте його в командному рядку, якщо це призводить до потрапляння в history або список процесів. Конкретні endpoint і формат запиту залежать від версії SurrealDB та використовуваного SDK, тому звіряйте приклад із документацією встановленого релізу.
Мінімальна перевірка доступності сервера виконується без передавання секрету:
curl -fsS https://db.example.com/health
Потім виконайте тестовий запит із тимчасового скрипту застосунку або офіційного CLI, передавши облікові дані через змінні середовища. Після перевірки видаліть тестові записи або використовуйте окремі базу та namespace.
Перевірка persistent storage
Переконайтеся, що каталог даних змонтований:
docker inspect surrealdb --format '{{range .Mounts}}{{println .Source " -> " .Destination}}{{end}}'
sudo du -sh /srv/surrealdb/data
sudo find /srv/surrealdb/data -maxdepth 2 -type f -ls | head
Щоб перевірити збереження після перезапуску, створіть тестовий запис, перезапустіть контейнер і прочитайте його знову. Робіть це в тестовому namespace, якщо база вже використовується застосунком.
docker compose restart surrealdb
docker compose ps
docker compose logs --tail=50 surrealdb
Налаштування обмежень ресурсів
Якщо на VPS працюють інші сервіси, задайте контейнеру розумні обмеження. Не встановлюйте ліміт пам’яті нижче фактичного робочого набору: у разі нестачі пам’яті процес може бути завершений OOM-killer.
services:
surrealdb:
deploy:
resources:
limits:
cpus: "4.0"
memory: 6G
reservations:
cpus: "1.0"
memory: 2G
У звичайному Docker Compose поле deploy підтримується не всіма режимами однаково. Перед застосуванням перевірте результат командою docker inspect. Найважливіше — залишити операційній системі щонайменше 1–2 ГБ RAM і стежити за swap, latency диска та OOM-подіями.
8. Резервні копії та обслуговування
Що необхідно зберігати
Резервна копія повинна містити дані бази, конфігурацію Compose, Caddyfile, каталог Caddy зі станом ACME та файл змінних середовища. Пароль із .env не можна публікувати у відкритому вигляді, тому репозиторій Restic має бути зашифрованим, а пароль Restic — зберігатися окремо.
/srv/surrealdb/data— постійні файли бази;/srv/surrealdb/compose.yml— опис контейнерів;/srv/surrealdb/Caddyfile— reverse proxy і TLS-налаштування;/srv/surrealdb/caddy/dataіcaddy/config— стан Caddy;- логічний експорт SurrealDB — незалежний від файлового формату рівень відновлення.
Не покладайтеся лише на копіювання живого каталогу бази. Для файлової бази важливо враховувати узгодженість даних. Логічний експорт, виконаний самим сервером, зазвичай простіше переносити між версіями та сховищами.
Підготовка S3 і Restic
Створіть окремий S3-бакет з обмеженими правами: лише запис і читання об’єктів резервної копії, без доступу до інших бакетів. Для Restic задайте змінні у файлі, доступному лише root:
sudo install -m 600 /dev/null /root/restic.env
sudo tee /root/restic.env >/dev/null <<'EOF'
export AWS_ACCESS_KEY_ID='REPLACE_ME'
export AWS_SECRET_ACCESS_KEY='REPLACE_ME'
export RESTIC_REPOSITORY='s3:https://s3.example.net/my-surrealdb-backups'
export RESTIC_PASSWORD='REPLACE_WITH_LONG_RESTIC_PASSWORD'
EOF
Не зберігайте цей файл у публічному Git-репозиторії. Якщо є штатний secret manager, краще завантажувати ключі звідти під час виконання завдання cron.
Скрипт щоденного бекапу
Створіть каталог для тимчасових експортів і скрипт:
sudo mkdir -p /var/lib/surrealdb-backup
sudo tee /usr/local/sbin/backup-surrealdb >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
PROJECT_DIR="/srv/surrealdb"
BACKUP_DIR="/var/lib/surrealdb-backup"
STAMP="$(date -u +%Y-%m-%dT%H-%M-%SZ)"
EXPORT_FILE="${BACKUP_DIR}/surrealdb-${STAMP}.surql"
source /root/restic.env
mkdir -p "$BACKUP_DIR"
cd "$PROJECT_DIR"
docker compose --env-file .env ps --status running surrealdb | grep -q surrealdb
docker exec surrealdb /surreal export \
--endpoint http://127.0.0.1:8000 \
--user "$SURREAL_ROOT_USER" \
--pass "$SURREAL_ROOT_PASSWORD" \
"$EXPORT_FILE"
restic backup \
"$EXPORT_FILE" \
"$PROJECT_DIR/compose.yml" \
"$PROJECT_DIR/Caddyfile" \
"$PROJECT_DIR/.env" \
"$PROJECT_DIR/caddy"
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--prune
rm -f "$EXPORT_FILE"
echo "Backup completed: $STAMP"
EOF
sudo chmod 700 /usr/local/sbin/backup-surrealdb
У деяких версіях CLI параметри експорту можуть відрізнятися. Виконайте docker exec surrealdb /surreal export --help і адаптуйте команду під встановлений реліз. Якщо CLI не може записати файл у шлях усередині контейнера, використовуйте тимчасовий каталог з окремим volume або виведення експорту в stdout із перенаправленням на хост.
Ініціалізація репозиторію та тестовий запуск
Ініціалізуйте зашифрований репозиторій Restic:
sudo bash -c 'source /root/restic.env && restic init'
sudo /usr/local/sbin/backup-surrealdb
Перевірте список знімків:
sudo bash -c 'source /root/restic.env && restic snapshots'
sudo bash -c 'source /root/restic.env && restic check'
Команда restic check перевіряє структуру репозиторію, але не доводить, що застосунок зможе відновити базу. Щонайменше раз на місяць виконуйте повне тестове відновлення в окремому тимчасовому каталозі або на тестовому VPS.
Планувальник cron
Створіть щоденне завдання із запуском, наприклад, о 03:15 UTC:
sudo tee /etc/cron.d/surrealdb-backup >/dev/null <<'EOF'
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
15 3 root /usr/local/sbin/backup-surrealdb >> /var/log/surrealdb-backup.log 2>&1
EOF
sudo chmod 644 /etc/cron.d/surrealdb-backup
sudo systemctl restart cron
Налаштуйте сповіщення про збій. Простий варіант — надсилати статус у зовнішній healthcheck-сервіс наприкінці скрипту; надійніший — використовувати моніторинг, який перевіряє час появи останнього знімка Restic і розмір репозиторію.
Відновлення експорту
Спочатку завантажте потрібний snapshot в окремий каталог:
sudo mkdir -p /var/lib/surrealdb-restore
sudo bash -c 'source /root/restic.env && restic restore latest --target /var/lib/surrealdb-restore'
sudo find /var/lib/surrealdb-restore -type f -name '.surql' -ls
Не імпортуйте дані поверх єдиної production-бази без вікна обслуговування та перевіреного плану. Запустіть тимчасовий контейнер в окремому каталозі, імпортуйте експорт, перевірте кількість записів і основні запити застосунку. Лише після цього плануйте відновлення production.
Оновлення SurrealDB
Оновлення має виконуватися в maintenance window:
- перевірити release notes і сумісність SurrealQL;
- створити ручний експорт;
- перевірити наявність свіжого Restic snapshot;
- змінити лише тег образу в
compose.yml; - запустити контейнер і перевірити health endpoint;
- виконати smoke-тести застосунку.
cd /srv/surrealdb
sudo /usr/local/sbin/backup-surrealdb
docker compose pull surrealdb
docker compose up -d surrealdb
docker compose ps
docker compose logs --tail=100 surrealdb
curl -fsS https://db.example.com/health
Для бази з одним екземпляром це не rolling update: на короткий час буде перерва. Rolling-схема вимагає сумісних версій, окремого екземпляра, продуманої реплікації та перевірки поведінки клієнтів. Не намагайтеся отримати безшовне оновлення простим запуском другого контейнера в тому самому каталозі даних.
Моніторинг
Контролюйте вільне місце, пам’ять, перезапуски контейнера, помилки в логах і затримку диска:
df -h
free -h
docker stats --no-stream
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
sudo journalctl -u docker --since "1 hour ago"
sudo dmesg -T | grep -i -E 'oom|killed process|ext4|nvme' || true
Алерт щодо диска варто вмикати вже при 70–80 відсотках заповнення, а не чекати 100 відсотків. У разі повного диска база може припинити записувати транзакції, а Caddy і Docker — створювати логи та тимчасові файли.
9. Troubleshooting і FAQ
Чому контейнер SurrealDB одразу завершує роботу?
Спочатку виконайте docker compose logs --tail=200 surrealdb і перевірте підсумкову конфігурацію командою docker compose config. Часті причини — неправильне ім’я змінної, помилка в параметрах start, недоступний каталог даних або несумісний тег образу. Також перевірте docker exec surrealdb /surreal version, якщо контейнер встигає запуститися. Не видаляйте каталог data до з’ясування причини.
Чому Caddy не отримує TLS-сертифікат?
Перевірте, що DNS-запис домену вказує на цей VPS, а порти 80 і 443 дозволені і в UFW, і у зовнішній security group. Виконайте curl -I http://db.example.com з іншої мережі та перегляньте docker compose logs caddy. Якщо на порту вже працює Nginx або Apache, зупиніть його або перенесіть сервіс. Також перевірте коректність email і відсутність тимчасового rate limit ACME.
Отримую timeout під час підключення до бази
Переконайтеся, що контейнер справний: docker compose ps і docker inspect surrealdb. Потім перевірте доступність Caddy через curl -v https://db.example.com/health. Порт 8000 навмисно не опублікований назовні, тому пряме підключення до SERVER_IP:8000 не повинно працювати. Якщо запити з Caddy не проходять, перевірте ім’я сервісу surrealdb і загальну Docker-мережу в Compose.
Яка конфігурація VPS мінімально підійде?
Для розробки достатньо 2 vCPU, 2–4 ГБ RAM і SSD від 40 ГБ. Для невеликої production-системи безпечніше почати з 2–4 vCPU, 8 ГБ RAM і NVMe від 80–100 ГБ. Оцінку потрібно робити за розміром бази, кількістю одночасних клієнтів, складністю запитів і обсягом застосунку на тому самому сервері. Залишайте не менше 30 відсотків диска вільними та не розміщуйте єдиний бекап на тому самому VPS.
Що вибрати — VPS чи dedicated для цього завдання?
VPS підходить для більшості невеликих і середніх установок: він дешевший, швидко масштабується та надає достатньо CPU, RAM і SSD. Dedicated виправданий за постійного високого навантаження, великих обсягів даних, вимог до стабільної продуктивності або коли на сервері працюватиме кілька ресурсоємних сервісів. Приймайте рішення за метриками, а не за передбачуваним престижем обладнання: спочатку виміряйте CPU, RAM, I/O і затримки запитів.
Дані зникли після пересоздання контейнера. Що зроблено неправильно?
Найімовірніше, контейнер запускався без bind mount або volume, або було видалено каталог /srv/surrealdb/data. Перевірте розділ volumes у Compose і вивід docker inspect surrealdb. Команда docker compose down -v може видалити іменовані volumes, тому не використовуйте її без розуміння наслідків. Якщо дані справді втрачені, відновіть останній логічний експорт або snapshot Restic на тестовий екземпляр.
Як змінити пароль root?
Не редагуйте пароль лише в .env, доки не зрозумієте, як саме поточна версія SurrealDB застосовує параметри запуску. Спочатку створіть свіжий бекап і вивчіть підтримувану процедуру зміни облікового запису для вашої версії. Після зміни секрету оновіть .env, перезапустіть контейнер і перевірте підключення застосунку. Старий пароль видаліть із shell history, тимчасових файлів і систем моніторингу.
Чи можна відкрити порт 8000 для підключення із застосунку?
Якщо застосунок знаходиться на тому самому VPS, підключайте його до Docker-мережі за адресою http://surrealdb:8000. Якщо backend працює на іншому сервері, безпечніше використовувати HTTPS через Caddy, private network або VPN, а не відкривати 8000 для всього інтернету. За потреби обмежте firewall конкретною IP-адресою застосунку і все одно використовуйте автентифікацію. Публічний endpoint має мати TLS і моніторинг спроб входу.
Чому резервна копія не створюється?
Запустіть скрипт вручну та перегляньте повний вивід. Перевірте доступ до S3, правильність endpoint, наявність змінних із /root/restic.env і вільне місце в /var/lib/surrealdb-backup. Потім виконайте restic snapshots і restic check. Окремо перевірте команду експорту через docker exec: зміна CLI між версіями може вимагати іншого порядку або назв аргументів. У cron завжди вказуйте абсолютні шляхи.
10. Висновки та наступні кроки
У результаті SurrealDB працює в Docker на VPS із постійним диском, HTTPS через Caddy, закритим внутрішнім портом і щоденним зашифрованим бекапом у S3. Конфігурація залишається відтворюваною: її можна перенести на новий сервер, відновити дані та зафіксувати версію образу.
Далі варто додати зовнішній нагляд за health endpoint і свіжістю бекапів, регулярно тестувати відновлення та оптимізувати індекси за реальними запитами. У разі зростання навантаження розділіть застосунок, базу та систему бекапів між окремими ресурсами, а перед переходом до кількох екземплярів спочатку перевірте сумісність реплікації та процедуру міграції.