PocketBase — открытый бэкенд, который поставляется как один исполняемый файл. Внутри: база данных SQLite, REST API, аутентификация пользователей, файловое хранилище, realtime-подписки и административная панель. Скачали, запустили — и через минуту у вас работающий API. PocketBase часто выбирают для MVP, внутренних инструментов и небольших продуктов, где Supabase избыточен, а писать бэкенд с нуля долго.
Что такое PocketBase и зачем он нужен
PocketBase — open-source проект на Go. Ключевые свойства:
- один бинарный файл без внешних зависимостей;
- встроенная SQLite (подробнее о самой СУБД — в статье что такое SQLite);
- REST API, который генерируется по схеме коллекций;
- встроенная аутентификация: email/пароль, OAuth2, OTP по email;
- административная панель по адресу
/_/; - расширение логики на JavaScript (
pb_hooks) или на Go, если использовать PocketBase как библиотеку.
По функциям PocketBase близок к Supabase, но разворачивается без Docker, PostgreSQL и Kubernetes. Важно помнить: проект ещё не достиг версии 1.0, и авторы прямо предупреждают, что между версиями возможны несовместимые изменения. Актуальную версию смотрите на странице GitHub Releases, а перед обновлением читайте changelog.
Установка PocketBase
Скачать и запустить локально
# Linux / macOS — подставьте актуальную версию с GitHub Releases
PB_VERSION=0.xx.x
wget https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip
unzip pocketbase_${PB_VERSION}_linux_amd64.zip
chmod +x pocketbase
./pocketbase serve
На Windows скачайте архив pocketbase_<версия>_windows_amd64.zip, распакуйте и выполните pocketbase.exe serve.
После запуска в терминале появятся адреса:
Server started at http://127.0.0.1:8090
├─ REST API: http://127.0.0.1:8090/api/
└─ Dashboard: http://127.0.0.1:8090/_/
При первом запуске PocketBase выведет ссылку для создания аккаунта superuser. Откройте её — и можно работать.
Что появится рядом с бинарником:
./
├── pocketbase # исполняемый файл
├── pb_data/ # данные: БД, загруженные файлы
│ ├── data.db # основная SQLite-база (коллекции, записи, настройки)
│ ├── auxiliary.db # вспомогательная база (логи запросов)
│ └── storage/ # загруженные файлы
└── pb_migrations/ # миграции (если вы их используете)
Запуск через Docker
# Dockerfile
FROM alpine:latest
ARG PB_VERSION=0.xx.x
RUN apk add --no-cache unzip ca-certificates && \
wget https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip && \
unzip pocketbase_${PB_VERSION}_linux_amd64.zip && \
rm pocketbase_${PB_VERSION}_linux_amd64.zip
EXPOSE 8090
CMD ["/pocketbase", "serve", "--http=0.0.0.0:8090"]
# docker-compose.yml
services:
pocketbase:
build: .
ports:
- "8090:8090"
volumes:
- ./pb_data:/pb_data
- ./pb_migrations:/pb_migrations
restart: unless-stopped
Главное — вынести pb_data в volume: всё состояние приложения живёт там. Как бэкапить такие тома, разобрано в статье про бэкап БД в Docker и Coolify.
Создание коллекций
Коллекции в PocketBase — это таблицы с автоматически сгенерированным API. Создаются через панель или через API.
Создание коллекции через панель
- Откройте
http://localhost:8090/_/. - Нажмите «New collection».
- Укажите название, например
posts. - Добавьте поля:
title— Text, обязательное;content— Editor (rich text);author— Relation → users;cover_image— File, максимум 1 файл;tags— Select с множественным выбором;published— Bool.
- Сохраните.
PocketBase сразу создаст REST-эндпоинты:
GET /api/collections/posts/records — список записей
POST /api/collections/posts/records — создать запись
GET /api/collections/posts/records/:id — одна запись
PATCH /api/collections/posts/records/:id — обновить
DELETE /api/collections/posts/records/:id — удалить
Основные типы полей
| Тип | Описание | Пример | |---|---|---| | Text | Строка | Заголовок, имя | | Number | Число | Цена, количество | | Bool | Да/нет | Опубликован | | Email | Email с валидацией | user@example.com | | URL | URL с валидацией | https://example.com | | DateTime | Дата и время | 2026-05-01 12:00 | | Autodate | Автоматические created/updated | Время создания | | Select | Выбор из вариантов | status: draft/published | | File | Файл или изображение | Обложка, аватар | | Relation | Связь с другой коллекцией | author → users | | Editor | Rich text (HTML) | Текст статьи | | JSON | Произвольный JSON | Настройки, метаданные |
Аутентификация в PocketBase
Коллекция users
При первом запуске PocketBase создаёт auth-коллекцию users. Поддерживаются:
- email + пароль;
- OAuth2 (Google, GitHub, Apple, Discord, GitLab и другие провайдеры, а также универсальный OpenID Connect);
- одноразовые коды (OTP) по email.
Регистрация и вход через JavaScript SDK
import PocketBase from 'pocketbase';
const pb = new PocketBase('http://localhost:8090');
// Регистрация
await pb.collection('users').create({
email: 'alex@example.com',
password: 'securepassword123',
passwordConfirm: 'securepassword123',
name: 'Алексей'
});
// Вход по email и паролю
await pb.collection('users').authWithPassword(
'alex@example.com',
'securepassword123'
);
// pb.authStore.record — текущий пользователь
// pb.authStore.token — токен, SDK сам добавляет его в заголовки
console.log(pb.authStore.record);
// Вход через OAuth2
await pb.collection('users').authWithOAuth2({ provider: 'google' });
// Обновление профиля
await pb.collection('users').update(pb.authStore.record.id, {
name: 'Алексей Иванов',
avatar: fileObject // объект File
});
// Выход
pb.authStore.clear();
В старых версиях SDK текущий пользователь лежал в pb.authStore.model; в актуальных — в pb.authStore.record.
API Rules — управление доступом
Доступ к записям задаётся API Rules — выражениями-фильтрами для операций list, view, create, update и delete.
# Список постов: публичный
listRule: ""
# Просмотр: опубликованные — всем, черновики — автору
viewRule: published = true || author = @request.auth.id
# Создание: только авторизованные
createRule: @request.auth.id != ""
# Обновление и удаление: только автор
updateRule: author = @request.auth.id
deleteRule: author = @request.auth.id
@request.auth.id — ID текущего пользователя. По смыслу это похоже на Row-Level Security в PostgreSQL, но настраивается в панели без SQL. Синтаксис, операторы и типовые ошибки подробно разобраны в статье API Rules в PocketBase.
Работа с файлами
// Создание записи с файлом
const formData = new FormData();
formData.append('title', 'Моя статья');
formData.append('cover_image', fileInput.files[0]);
const record = await pb.collection('posts').create(formData);
// URL файла
const imageUrl = pb.files.getURL(record, record.cover_image);
// http://localhost:8090/api/files/posts/RECORD_ID/IMAGE_NAME.jpg
// URL миниатюры 100x100 (размеры миниатюр задаются в настройках поля)
const thumbUrl = pb.files.getURL(record, record.cover_image, { thumb: '100x100' });
По умолчанию файлы хранятся в pb_data/storage/. В настройках можно переключить хранение файлов на S3-совместимое хранилище.
Realtime-подписки
Realtime в PocketBase работает через Server-Sent Events:
// Подписка на все изменения коллекции
pb.collection('messages').subscribe('*', (e) => {
console.log(e.action); // "create" | "update" | "delete"
console.log(e.record);
if (e.action === 'create') {
addMessageToUI(e.record);
}
});
// Подписка на одну запись
pb.collection('orders').subscribe('ORDER_ID', (e) => {
updateOrderStatus(e.record.status);
});
// Отписка
pb.collection('messages').unsubscribe();
JavaScript SDK: работа с коллекциями
import PocketBase from 'pocketbase';
const pb = new PocketBase('https://your-pocketbase.com');
// Список с фильтром, сортировкой и пагинацией
const posts = await pb.collection('posts').getList(1, 20, {
filter: 'published = true && created >= "2026-01-01"',
sort: '-created',
expand: 'author',
fields: 'id,title,created,expand.author.name'
});
// posts.items, posts.totalItems, posts.totalPages
// Все записи без пагинации
const allTags = await pb.collection('tags').getFullList({ sort: 'name' });
// Одна запись
const post = await pb.collection('posts').getOne('RECORD_ID', {
expand: 'author'
});
// Первая запись по фильтру
const latestPost = await pb.collection('posts').getFirstListItem(
'published = true',
{ sort: '-created' }
);
// Создание, обновление, удаление
const newPost = await pb.collection('posts').create({
title: 'Новая статья',
content: '<p>Содержимое</p>',
author: pb.authStore.record.id,
published: false
});
await pb.collection('posts').update('RECORD_ID', { published: true });
await pb.collection('posts').delete('RECORD_ID');
Расширение PocketBase своей логикой
Хуки и свои маршруты можно писать на JavaScript (файлы *.pb.js в pb_hooks/) или на Go.
// pb_hooks/main.pb.js
// Перед созданием записи — подставить автора
onRecordCreateRequest((e) => {
if (e.auth) {
e.record.set('author', e.auth.id);
}
e.next();
}, 'posts');
// После успешного создания — письмо автору
onRecordAfterCreateSuccess((e) => {
e.next();
const author = $app.findRecordById('users', e.record.getString('author'));
const message = new MailerMessage({
from: {
address: $app.settings().meta.senderAddress,
name: $app.settings().meta.senderName,
},
to: [{ address: author.email() }],
subject: 'Статья создана',
html: `<p>Ваша статья "${e.record.getString('title')}" создана.</p>`,
});
$app.newMailClient().send(message);
}, 'posts');
// Свой API-маршрут
routerAdd('POST', '/api/custom/send-notification', (e) => {
const data = e.requestInfo().body;
// ваша логика
return e.json(200, { status: 'sent' });
});
Деплой PocketBase на VPS
Ubuntu/Debian + systemd + Nginx
# 1. Скачать PocketBase
PB_VERSION=0.xx.x
wget https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip
unzip pocketbase_${PB_VERSION}_linux_amd64.zip -d /opt/pocketbase
chmod +x /opt/pocketbase/pocketbase
chown -R www-data:www-data /opt/pocketbase
# 2. systemd-сервис
cat > /etc/systemd/system/pocketbase.service << 'EOF'
[Unit]
Description=PocketBase
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/pocketbase
ExecStart=/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now pocketbase
# 3. Nginx как реверс-прокси (настройки под SSE для realtime)
cat > /etc/nginx/sites-available/pocketbase << 'EOF'
server {
listen 80;
server_name your-domain.com;
client_max_body_size 10M;
location / {
proxy_set_header Connection '';
proxy_http_version 1.1;
proxy_read_timeout 360s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8090;
}
}
EOF
ln -s /etc/nginx/sites-available/pocketbase /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
# 4. TLS через Certbot
certbot --nginx -d your-domain.com
Деплой через Coolify
Если на VPS уже стоит Coolify, PocketBase можно поднять из Dockerfile выше (или из готового шаблона сервиса, если он есть в вашем каталоге Coolify). Обязательные пункты: постоянный volume для /pb_data, порт 8090 и домен с TLS.
Бэкап PocketBase
Всё состояние PocketBase — в каталоге pb_data: база data.db и загруженные файлы в storage/. Потеряли каталог — потеряли пользователей, записи и настройки.
Встроенный механизм: в панели (Settings → Backups) PocketBase умеет создавать zip-архив pb_data вручную или по cron-расписанию и складывать его локально в pb_data/backups или в S3. Это хорошая база, но архивы на том же сервере не спасут при потере диска, а проверять их содержимое придётся вручную.
Если копируете базу сами, не делайте cp data.db на работающем сервере: PocketBase использует WAL-режим, и часть транзакций может лежать в файле data.db-wal. Используйте sqlite3 .backup или VACUUM INTO — подробности в статье как сделать бэкап SQLite без повреждения.
Пример выгрузки в бэкапы SQLite в dbsend:
npm install --global @dbsend/sdk
dbsend login --key sqv_pk_...
# База: CLI сам делает консистентную копию SQLite перед загрузкой
dbsend backup /opt/pocketbase/pb_data/data.db -d "$DBSEND_DATABASE_ID" -e sqlite -l nightly
# Загруженные файлы — отдельным архивом как generic_file
tar -czf /tmp/pb_storage.tar.gz -C /opt/pocketbase/pb_data storage
dbsend backup /tmp/pb_storage.tar.gz -d "$DBSEND_FILES_ID" -e generic_file
Каждая загрузка становится версией базы; для SQLite dbsend показывает таблицы и число строк и умеет сравнивать версии. Пошаговая схема с cron, ротацией и восстановлением — в статье бэкап PocketBase.
PocketBase vs Supabase vs Firebase
| Параметр | PocketBase | Supabase | Firebase | |---|---|---|---| | База данных | SQLite | PostgreSQL | Firestore (NoSQL) | | Деплой | Один файл | Облако или Docker | Только облако | | Self-hosted | Просто | Сложнее (много сервисов) | Нет | | Масштабирование | Вертикальное, один сервер | Высокое | Высокое | | Цена | Бесплатно при self-host, платите за VPS | Есть бесплатный облачный тариф | Есть бесплатный тариф | | Аутентификация | Встроенная | Встроенная | Встроенная | | Realtime | SSE | WebSocket | Нативный | | Официальные SDK | JS, Dart | JS, Dart, Python, Swift и др. | iOS, Android, Web и др. | | Данные в России | Да, при self-host на российском VPS | Только self-host | Нет |
Выбирайте PocketBase, если:
- делаете MVP или прототип и нужно запуститься быстро;
- хватает одного сервера и нагрузка предсказуема;
- хотите self-hosted бэкенд на недорогом VPS;
- пишете код с AI-ассистентом: по PocketBase много документации и примеров.
Выбирайте Supabase, если:
- нужен полноценный PostgreSQL и SQL;
- команда знает PostgreSQL и RLS;
- ожидается рост, который один сервер не вытянет.
Выбирайте Firebase, если:
- делаете мобильное приложение и нужны зрелые нативные SDK;
- важна интеграция с Google Analytics и Crashlytics.
Ограничения PocketBase
SQLite не масштабируется горизонтально. Один процесс, один сервер, один писатель в каждый момент. Для большинства небольших проектов этого хватает, но при росте нагрузки на запись или требовании нескольких серверов придётся переходить на PostgreSQL.
Нет полноценной очереди задач. Есть встроенный планировщик (cronAdd в хуках), но для тяжёлых фоновых задач нужна внешняя очередь.
API ещё не v1.0. Перед каждым обновлением читайте changelog и делайте бэкап pb_data.
JavaScript в хуках — не Node.js. Встроенный движок goja поддерживает ES5 и большую часть ES6, но npm-пакеты, завязанные на Node API, работать не будут. Для сложной логики используйте Go.
Полнотекстовый поиск по русскому тексту ограничен. Фильтр ~ — это LIKE, без морфологии. Для серьёзного поиска подключают Meilisearch или аналог.
Частые вопросы
Подходит ли PocketBase для production?
Да, для многих проектов: внутренние инструменты, MVP, небольшие SaaS. Но учитывайте, что до v1.0 возможны несовместимые изменения, а масштабирование ограничено одним сервером. Для систем с высокой нагрузкой на запись или требованием отказоустойчивости на нескольких узлах лучше PostgreSQL.
Как обновлять PocketBase без потери данных?
Сделайте бэкап pb_data, затем замените бинарник новой версией (для готового бинарника есть команда ./pocketbase update). Данные в pb_data/ сохраняются, нужные системные миграции PocketBase применит при старте. Если обновление пошло не так, вы откатываетесь на старый бинарник и копию pb_data.
Можно ли использовать PocketBase как Go-фреймворк?
Да. PocketBase подключается к Go-проекту как библиотека: вы добавляете свои маршруты, хуки и логику и собираете один бинарник.
Как подключить PocketBase к React или Next.js?
Установите SDK npm install pocketbase и создайте клиент в отдельном модуле. В Next.js для серверных компонентов создавайте новый экземпляр на каждый запрос и восстанавливайте сессию из cookie, а клиентскую авторизацию оставьте в client components. Пример — в статье PocketBase как бэкенд.
Какой максимальный размер файла?
Он задаётся в настройках поля File (параметр максимального размера). Для больших файлов включите S3-совместимое хранилище в настройках PocketBase.
Как настроить автоматический бэкап PocketBase?
Три варианта: встроенные бэкапы в панели (Settings → Backups, локально или в S3); свой cron-скрипт с sqlite3 .backup и выгрузкой в S3; загрузка копий в dbsend с версиями, сравнением и алертами, если бэкап не пришёл по расписанию. В любом варианте периодически проверяйте восстановление на тестовой машине.



