Развёртывание Apache Superset на VPS: Docker, PostgreSQL, Redis, SSL и подключение баз данных
TL;DR
Apache Superset можно развернуть на VPS в Docker Compose с отдельными контейнерами PostgreSQL, Redis, Celery и Caddy: в результате получится собственная защищённая BI-платформа для дашбордов, SQL-запросов и подключения внешних баз данных через HTTPS.
- Для небольшого production-развёртывания достаточно 4 vCPU, 8 ГБ RAM и 80–120 ГБ NVMe-диска.
- PostgreSQL хранит метаданные Superset: пользователей, настройки, чарты, дашборды и подключения.
- Redis используется как брокер Celery-задач и кэш результатов запросов.
- Caddy автоматически выпускает и обновляет TLS-сертификаты Let’s Encrypt.
- Внешние аналитические БД подключаются из интерфейса Superset или через SQLAlchemy URI.
- Для production обязательно задайте постоянный
SECRET_KEY, включите резервное копирование PostgreSQL и ограничьте доступ к серверу firewall-правилами.
Что мы настраиваем и зачем
Apache Superset — open-source BI-платформа для работы с данными. Через веб-интерфейс она позволяет подключать PostgreSQL, MySQL, ClickHouse, Microsoft SQL Server, Trino, BigQuery, Snowflake, DuckDB и десятки других источников через SQLAlchemy-драйверы. Пользователь создаёт наборы данных, SQL-запросы, графики, таблицы, KPI-карточки и интерактивные дашборды.
В этом руководстве будет развёрнут production-стек Apache Superset на Ubuntu Server 24.04 LTS. Superset запускается в Docker Compose, метаданные хранятся в PostgreSQL 16, Redis 7 используется для очередей и кэширования, а Caddy принимает HTTPS-трафик на портах 80 и 443. Веб-контейнер Superset не публикуется напрямую в интернет: наружу доступен только reverse proxy.
Архитектура подходит для небольшой команды, стартапа, внутренней аналитики SaaS-продукта, агентства или отдела до нескольких десятков активных пользователей. Она также удобна для персональной аналитической среды: например, когда данные приложения лежат в PostgreSQL, события собираются в ClickHouse, а отчёты необходимо предоставлять менеджерам без прямого доступа к базам.
| Компонент | Назначение | Доступ извне |
|---|---|---|
| Apache Superset | Веб-интерфейс BI, SQL Lab, чарты и дашборды | Только через Caddy |
| PostgreSQL 16 | Метаданные Superset, пользователи, роли, подключения | Нет |
| Redis 7 | Celery broker, результаты задач, кэш | Нет |
| Celery worker | Асинхронные запросы, отчёты, фоновые задачи | Нет |
| Caddy | HTTPS, reverse proxy, автоматические сертификаты | Порты 80 и 443 |
Что получится после настройки
После выполнения шагов у вас будет URL вида https://superset.example.com, защищённый действующим сертификатом TLS. Администратор сможет создавать пользователей, назначать им роли Gamma, Alpha или кастомные роли, регистрировать внешние базы данных и строить дашборды. Результаты долгих запросов смогут выполняться через Celery, не блокируя веб-процесс.
PostgreSQL в этой схеме не является базой для бизнес-данных. Он хранит именно служебное состояние Superset. Если удалить его volume без резервной копии, исчезнут учётные записи, подключения к данным, SQL-запросы, дашборды, теги и настройки. Поэтому PostgreSQL должен резервироваться регулярно, отдельно от образов Docker.
Self-hosted Superset и managed BI
Cloud-managed сервисы BI быстрее запускаются: обычно достаточно подключить хранилище данных и пригласить сотрудников. В обмен на это организация передаёт провайдеру метаданные, SQL-запросы, структуру таблиц, иногда результаты аналитики и данные пользователей. Кроме того, стоимость часто зависит от количества редакторов или просмотров.
Self-hosted Apache Superset на VPS требует самостоятельного администрирования, обновлений и резервного копирования. Зато вы контролируете сетевую топологию, версии, логи, роли, домен и место хранения данных. Это особенно полезно, если база доступна только во внутренней сети, действуют требования по локализации данных или аналитика должна работать без зависимости от внешнего SaaS.
Superset обычно не копирует данные в PostgreSQL метаданных. Он подключается к исходной БД и выполняет SQL-запросы от имени отдельного технического пользователя. Однако SQL Lab и кэш могут сохранять результаты на ограниченное время, поэтому права и срок хранения кэша нужно планировать заранее.
Какой VPS-конфиг нужен под эту задачу
Нагрузка Superset зависит не только от количества пользователей. Существеннее число одновременных SQL-запросов, объём результатов, сложность графиков, использование отчётов по расписанию и расположение аналитической базы. Сам Superset не должен выполнять тяжёлую агрегацию вместо ClickHouse, PostgreSQL или warehouse: расчёты нужно переносить в исходную БД, витрины или materialized views.
| Сценарий | vCPU | RAM | NVMe-диск | Подходит для |
|---|---|---|---|---|
| Тестовый стенд | 2 | 4 ГБ | 40–60 ГБ | 1–3 пользователя, без тяжёлых задач |
| Небольшой production | 4 | 8 ГБ | 80–120 ГБ | 5–30 активных пользователей |
| Команда и регулярные отчёты | 6–8 | 16 ГБ | 160–250 ГБ | 30–100 пользователей, Celery и кэш |
| Высокая нагрузка | 8+ | 32 ГБ+ | 300 ГБ+ | Несколько worker, много дашбордов |
Для первого production-развёртывания практичный минимум — 4 vCPU, 8 ГБ RAM, 100 ГБ NVMe и канал от 100 Мбит/с. На таком сервере нормально работают Superset, PostgreSQL, Redis, Caddy и один или два Celery worker-процесса. Оставляйте минимум 20–30% свободного диска для PostgreSQL WAL, Docker-слоёв, логов и бэкапов перед выгрузкой во внешнее хранилище.
Например, можно взять VPS с указанными характеристиками, установить Ubuntu 24.04 LTS и назначить статический публичный IPv4. При выборе проверьте, что провайдер не блокирует входящие порты 80 и 443: они нужны Caddy для HTTP-проверки домена и HTTPS.
Когда нужен dedicated, а не VPS
Выделенный сервер имеет смысл, если Superset обслуживает большое количество одновременных пользователей, на том же хосте запускаются тяжёлые ClickHouse или PostgreSQL-аналитика, необходимы 32–128 ГБ RAM, предсказуемые IOPS либо строгая изоляция ресурсов. Dedicated также предпочтителен при требованиях комплаенса, когда нельзя размещать производственные данные на виртуализированной инфраструктуре.
Если же Superset подключается к отдельному managed PostgreSQL, ClickHouse Cloud, BigQuery или удалённому warehouse, собственный сервер Superset обычно не требует мощного CPU. В этом случае чаще всего достаточно VPS с 4–8 vCPU и 8–16 ГБ RAM. Увеличивать ресурсы следует после наблюдения за RAM, очередью Celery, временем ответа и нагрузкой исходной базы.
Выбор локации
Локация влияет на задержку между Superset и источниками данных. Если PostgreSQL или ClickHouse находятся в европейском дата-центре, размещайте VPS Superset в том же регионе или хотя бы в той же стране. Задержка 2–10 мс почти не влияет на обычные запросы, но 80–150 мс заметно замедляет интерактивные фильтры и дашборды с десятками виджетов.
Если Superset доступен сотрудникам из одной страны, выбирайте ближайшую локацию. Если доступ ограничен корпоративной VPN, полезнее разместить сервер рядом с private network или VPN-шлюзом. Не открывайте PostgreSQL-источник в интернет ради подключения Superset: лучше использовать приватную сеть, WireGuard-туннель, SSH-tunnel или разрешение конкретного IP-адреса VPS.
Подготовка сервера
Инструкция рассчитана на чистую Ubuntu Server 24.04 LTS с доступом по SSH под пользователем root. Перед началом создайте DNS-запись типа A: superset.example.com должна указывать на публичный IPv4 сервера. Caddy не сможет выпустить сертификат, пока DNS не распространится и порты 80/443 не будут доступны извне.
Создание администратора и обновление ОС
Не запускайте Docker-стек постоянно от root. Создайте отдельного пользователя, добавьте его в группы sudo и docker, а затем используйте его для дальнейших действий.
apt update && apt upgrade -y
apt install -y sudo curl wget ca-certificates gnupg lsb-release \
ufw fail2ban unattended-upgrades jq nano git
adduser deploy
usermod -aG sudo deploy
Команда устанавливает обновления безопасности, базовые утилиты, firewall и fail2ban, затем создаёт пользователя deploy. Пароль пользователя понадобится только как резервный вариант: основным способом доступа должны быть SSH-ключи.
Настройка SSH-ключа
На локальном компьютере создайте ключ, если его ещё нет. Для нового ключа используйте Ed25519 и задайте passphrase. Затем скопируйте публичную часть на сервер.
ssh-keygen -t ed25519 -a 100 -C "[email protected]"
ssh-copy-id deploy@SERVER_IP
ssh deploy@SERVER_IP
Проверьте, что вход пользователем deploy работает в отдельном терминале. Только после этой проверки отключайте вход root и парольную аутентификацию. Не закрывайте текущую root-сессию, пока не подтвердите доступ по ключу.
sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
Создайте файл со следующим содержимым.
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
MaxAuthTries 3
AllowUsers deploy
Проверьте конфигурацию и перезапустите SSH-службу.
sudo sshd -t && sudo systemctl restart ssh
Firewall и fail2ban
Внешнему интернету нужны только SSH, HTTP и HTTPS. Не открывайте порт Superset 8088, Redis 6379 и PostgreSQL 5432: между контейнерами они работают во внутренней Docker-сети.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
В идеале ограничьте SSH конкретным офисным IP или VPN-подсетью. Если IP динамический, оставьте OpenSSH открытым, но используйте только ключи и fail2ban.
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
sudo systemctl enable --now unattended-upgrades
Fail2ban блокирует IP после повторяющихся неудачных попыток входа. Автоматические обновления Ubuntu ставят security-патчи, но Docker-образы Superset, PostgreSQL и Redis всё равно нужно обновлять вручную по контролируемому расписанию.
Проверка ресурсов до установки
free -h
df -h /
nproc
curl -4 ifconfig.me
Убедитесь, что доступно не менее 7 ГБ оперативной памяти для рекомендуемого сценария, на диске есть минимум 70 ГБ свободного места, а команда curl возвращает ожидаемый публичный IP. Если RAM ровно 4 ГБ, создайте swap 2–4 ГБ: он не заменяет память, но может предотвратить аварийное завершение процесса при кратковременном пике.
Установка ПО — пошагово
Ниже используется Docker Engine и Docker Compose Plugin из официального репозитория Docker. На 2026 год ориентируйтесь на актуальную стабильную ветку Docker Engine 27/28 и Compose v2; точные версии можно увидеть после установки. Для Superset в примере закреплён образ apache/superset:5.0.0. Перед production-обновлением проверьте страницу релизов Apache Superset и changelog выбранного тега.
Установка Docker Engine
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Команды добавляют официальный GPG-ключ Docker в системное хранилище ключей APT.
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
Этот блок добавляет официальный репозиторий Docker для Ubuntu 24.04.
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker deploy
newgrp docker
docker version
docker compose version
После добавления в группу docker войдите заново по SSH либо выполните newgrp docker. Членство в этой группе фактически даёт root-полномочия на хосте, поэтому добавляйте в неё только доверенных администраторов.
Создание структуры проекта
Разместим конфигурацию в /opt/superset. Каталог будет содержать Compose-файл, переменные окружения, конфигурацию приложения, Caddyfile и скрипты обслуживания. Docker volumes будут управляться Docker отдельно.
sudo mkdir -p /opt/superset/{config,caddy,data,backups,scripts}
sudo chown -R deploy:deploy /opt/superset
cd /opt/superset
umask 077
openssl rand -base64 48
openssl rand -hex 24
Последние две команды генерируют секреты. Первый длинный случайный ключ сохраните как SUPERSET_SECRET_KEY, второй используйте как пароль PostgreSQL. Не вставляйте эти значения в Git, тикеты, скриншоты или общий чат.
Создание файла переменных
cd /opt/superset
nano .env
chmod 600 .env
Файл .env будет прочитан Docker Compose, но не должен быть доступен другим пользователям системы.
SUPERSET_TAG=5.0.0
SUPERSET_SECRET_KEY=PASTE_A_LONG_RANDOM_BASE64_SECRET_HERE
POSTGRES_DB=superset
POSTGRES_USER=superset
POSTGRES_PASSWORD=PASTE_A_LONG_RANDOM_PASSWORD_HERE
POSTGRES_HOST=db
POSTGRES_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379
SUPERSET_DOMAIN=superset.example.com
[email protected]
TZ=Europe/Moscow
Замените домен, email, часовой пояс и оба секрета. Ключ Superset нельзя менять после запуска без специальной процедуры ротации: зашифрованные значения, например пароли подключений к БД, перестанут расшифровываться.
Сборка кастомного образа с драйверами
Базовый образ Superset не обязан включать все драйверы нужных источников. Для PostgreSQL, MySQL и ClickHouse создадим небольшой производный образ. Если драйвер не нужен, его можно удалить из файла.
nano Dockerfile
nano requirements-local.txt
ARG SUPERSET_TAG=5.0.0
FROM apache/superset:${SUPERSET_TAG}
USER root
COPY requirements-local.txt /tmp/requirements-local.txt
RUN pip install --no-cache-dir -r /tmp/requirements-local.txt
USER superset
psycopg2-binary==2.9.10
pymysql==1.1.1
clickhouse-connect==0.8.15
trino==0.333.0
duckdb-engine==0.13.4
Здесь добавлены драйверы для наиболее распространённых источников. Не устанавливайте пакеты без необходимости: каждый драйвер расширяет поверхность обновлений. Для Microsoft SQL Server может потребоваться отдельный драйвер pymssql или pyodbc и системные библиотеки.
Создание конфигурации Superset
nano config/superset_config.py
В следующем разделе будет приведено полное содержимое этого файла. После его создания создайте Compose-описание.
nano compose.yaml
Compose-файл запускает шесть сервисов: PostgreSQL, Redis, Superset web, Celery worker, Celery beat и Caddy. Команда docker compose up -d --build соберёт локальный образ и создаст внутреннюю сеть.
docker compose config
docker compose build
docker compose up -d
docker compose ps
Команда docker compose config сначала проверяет синтаксис и подстановку переменных. Не переходите к инициализации, пока все контейнеры не получат состояние running или не станет понятна причина ошибки через логи.
docker compose logs --tail=100 db
docker compose logs --tail=100 superset
docker compose logs --tail=100 worker
Просмотр логов сразу после первого запуска помогает обнаружить неверный пароль PostgreSQL, занятый порт, ошибку Python-драйвера или отсутствие памяти до настройки домена и HTTPS.
Конфигурация Superset, PostgreSQL, Redis и SSL
Конфигурация приложения Superset
Файл config/superset_config.py передаётся в контейнер как /app/pythonpath/superset_config.py. Он задаёт URI метаданных, Redis-кэш, Celery, прокси-заголовки и ограничения загрузки. Секреты берутся только из environment variables.
import os
from cachelib.redis import RedisCache
SECRET_KEY = os.environ["SUPERSET_SECRET_KEY"]
SQLALCHEMY_DATABASE_URI = (
f"postgresql+psycopg2://{os.environ['POSTGRES_USER']}:"
f"{os.environ['POSTGRES_PASSWORD']}@"
f"{os.environ['POSTGRES_HOST']}:"
f"{os.environ['POSTGRES_PORT']}/{os.environ['POSTGRES_DB']}"
)
REDIS_HOST = os.environ.get("REDIS_HOST", "redis")
REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
CACHE_CONFIG = {
"CACHE_TYPE": "RedisCache",
"CACHE_DEFAULT_TIMEOUT": 300,
"CACHE_KEY_PREFIX": "superset_cache_",
"CACHE_REDIS_HOST": REDIS_HOST,
"CACHE_REDIS_PORT": REDIS_PORT,
"CACHE_REDIS_DB": 1,
}
DATA_CACHE_CONFIG = CACHE_CONFIG
class CeleryConfig:
broker_url = REDIS_URL
result_backend = "redis://redis:6379/2"
imports = (
"superset.sql_lab",
"superset.tasks",
"superset.tasks.thumbnails",
"superset.tasks.reports",
)
worker_prefetch_multiplier = 1
task_acks_late = True
beat_schedule = {}
CELERY_CONFIG = CeleryConfig
FEATURE_FLAGS = {
"ALERT_REPORTS": True,
"THUMBNAILS": True,
"DASHBOARD_RBAC": True,
}
ENABLE_PROXY_FIX = True
WTF_CSRF_ENABLED = True
WTF_CSRF_EXEMPT_LIST = []
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Lax"
PREFERRED_URL_SCHEME = "https"
SUPERSET_WEBSERVER_TIMEOUT = 120
SQLLAB_TIMEOUT = 300
ROW_LIMIT = 100000
VIZ_ROW_LIMIT = 100000
UPLOAD_FOLDER = "/app/superset_home/uploads"
MAX_CONTENT_LENGTH = 50 1024 1024
TALISMAN_ENABLED = False
Параметр ENABLE_PROXY_FIX необходим, чтобы Superset правильно видел HTTPS за Caddy и не генерировал небезопасные ссылки. Значение TALISMAN_ENABLED = False упрощает начальный запуск: при дальнейшем усилении CSP настройте заголовки осознанно, поскольку строгая Content Security Policy может блокировать визуализации и плагины.
Compose-файл
Сохраните следующий файл как /opt/superset/compose.yaml. Порты PostgreSQL, Redis и Superset не опубликованы на хост. Единственный опубликованный сервис — Caddy.
services:
db:
image: postgres:16.8
container_name: superset-db
restart: unless-stopped
env_file: .env
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
TZ: ${TZ}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 10
networks:
- superset_internal
redis:
image: redis:7.4-alpine
container_name: superset-redis
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes", "--save", "60", "1000"]
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 10
networks:
- superset_internal
superset:
build:
context: .
args:
SUPERSET_TAG: ${SUPERSET_TAG}
image: local/superset:${SUPERSET_TAG}
container_name: superset-web
restart: unless-stopped
env_file: .env
environment:
SUPERSET_CONFIG_PATH: /app/pythonpath/superset_config.py
PYTHONPATH: /app/pythonpath
TZ: ${TZ}
command: ["/usr/bin/run-server.sh"]
volumes:
- ./config/superset_config.py:/app/pythonpath/superset_config.py:ro
- superset_home:/app/superset_home
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
expose:
- "8088"
networks:
- superset_internal
worker:
image: local/superset:${SUPERSET_TAG}
container_name: superset-worker
restart: unless-stopped
env_file: .env
environment:
SUPERSET_CONFIG_PATH: /app/pythonpath/superset_config.py
PYTHONPATH: /app/pythonpath
TZ: ${TZ}
command: ["celery", "--app=superset.tasks.celery_app:app", "worker", "-O", "fair", "-l", "INFO", "-c", "2"]
volumes:
- ./config/superset_config.py:/app/pythonpath/superset_config.py:ro
- superset_home:/app/superset_home
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- superset_internal
beat:
image: local/superset:${SUPERSET_TAG}
container_name: superset-beat
restart: unless-stopped
env_file: .env
environment:
SUPERSET_CONFIG_PATH: /app/pythonpath/superset_config.py
PYTHONPATH: /app/pythonpath
TZ: ${TZ}
command: ["celery", "--app=superset.tasks.celery_app:app", "beat", "-l", "INFO"]
volumes:
- ./config/superset_config.py:/app/pythonpath/superset_config.py:ro
- superset_home:/app/superset_home
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- superset_internal
caddy:
image: caddy:2.8-alpine
container_name: superset-caddy
restart: unless-stopped
env_file: .env
ports:
- "80:80"
- "443:443"
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
- superset
networks:
- superset_internal
networks:
superset_internal:
name: superset_internal
volumes:
postgres_data:
redis_data:
superset_home:
caddy_data:
caddy_config:
Redis persistence включён через AOF. Для кэша это не критично, но помогает сохранить часть состояния очередей после короткого рестарта. Источником истины остаётся PostgreSQL. У контейнера worker задана конкурентность -c 2; на сервере с 8 ГБ RAM не увеличивайте её без наблюдения за памятью.
Caddy и автоматический TLS
Создайте файл /opt/superset/caddy/Caddyfile. Caddy получит сертификат Let’s Encrypt автоматически, если DNS уже указывает на сервер и порты 80/443 свободны.
nano /opt/superset/caddy/Caddyfile
{
email {$LETSENCRYPT_EMAIL}
auto_https on
}
{$SUPERSET_DOMAIN} {
encode zstd gzip
reverse_proxy superset:8088 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
log {
output stdout
format console
}
}
После сохранения файлов соберите и поднимите стек. Первый запуск требует отдельной инициализации схемы и создания администратора.
cd /opt/superset
docker compose up -d --build
docker compose exec superset superset db upgrade
docker compose exec superset superset fab create-admin \
--username admin \
--firstname Superset \
--lastname Admin \
--email [email protected] \
--password 'CHANGE_THIS_PASSWORD_NOW'
docker compose exec superset superset init
docker compose restart superset worker beat caddy
Команда superset db upgrade применяет миграции metadata database. create-admin создаёт локального администратора, а superset init создаёт роли и базовые разрешения. Сразу после входа смените временный пароль на уникальный пароль из менеджера паролей.
Проверка работоспособности
docker compose ps
docker compose exec db pg_isready -U superset -d superset
docker compose exec redis redis-cli ping
curl -I http://127.0.0.1
curl -I https://superset.example.com
docker compose logs --tail=100 caddy
Ожидаемый ответ Redis — PONG. Запрос к HTTPS должен вернуть HTTP/2 200 или HTTP/2 302 на страницу логина. Если Caddy возвращает ошибку сертификата, сначала проверьте DNS, firewall и логи docker compose logs caddy.
Подключение внешних баз данных
Создавайте в каждой аналитической БД отдельного технического пользователя только на чтение. Не используйте root, postgres, sa или владельца схемы. Для Superset обычно достаточно прав CONNECT, USAGE на нужные схемы и SELECT на таблицы или views.
Пример для PostgreSQL-источника. Выполните его на сервере базы данных, заменив имя БД, схему и пароль.
CREATE ROLE superset_reader LOGIN PASSWORD 'LONG_UNIQUE_PASSWORD';
GRANT CONNECT ON DATABASE appdb TO superset_reader;
GRANT USAGE ON SCHEMA analytics TO superset_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO superset_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA analytics
GRANT SELECT ON TABLES TO superset_reader;
В интерфейсе Superset откройте Settings → Database Connections → + Database. Для PostgreSQL URI будет выглядеть так:
postgresql+psycopg2://superset_reader:[email protected]:5432/appdb
Если пароль содержит символы @, :, / или #, URL-кодируйте его. Например, @ превращается в %40. В настройках подключения включите Expose in SQL Lab, если пользователям нужен SQL Lab, и отключите Allow DML, если редактирование данных не требуется.
Для ClickHouse с драйвером clickhouse-connect используйте URI следующего вида:
clickhousedb://superset_reader:[email protected]:8123/analytics
При подключении через публичную сеть включайте TLS на стороне источника, используйте private networking или WireGuard. Не храните production-пароли в описаниях дашбордов, SQL-комментариях и переменных, которые могут попасть в экспорт.
Бэкапы и обслуживание
Минимальный бэкап Superset должен включать PostgreSQL metadata database, файл .env, compose.yaml, config/superset_config.py, Caddyfile и при необходимости Docker volume superset_home. Наиболее важен дамп PostgreSQL: в нём находятся все объекты интерфейса и зашифрованные данные подключений.
Не считайте Docker volume резервной копией. Volume находится на том же диске, что и сервер, и не защитит от удаления VPS, ошибки администратора, сбоя файловой системы или ransomware. Следуйте правилу 3-2-1: минимум три копии, на двух типах носителей, одна копия вне основного сервера.
Скрипт резервного копирования PostgreSQL
Ниже скрипт делает сжатый дамп, копирует конфигурацию и затем может передать архив в S3-совместимое хранилище через restic. Restic шифрует данные на клиенте; пароль репозитория храните отдельно в менеджере секретов.
sudo apt install -y restic
mkdir -p /opt/superset/backups
nano /opt/superset/scripts/backup.sh
chmod 700 /opt/superset/scripts/backup.sh
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/opt/superset"
DATE="$(date +%F_%H-%M-%S)"
BACKUP_DIR="${BASE_DIR}/backups/${DATE}"
mkdir -p "${BACKUP_DIR}"
cd "${BASE_DIR}"
docker compose exec -T db pg_dump \
-U "${POSTGRES_USER}" \
-d "${POSTGRES_DB}" \
--format=custom \
--no-owner \
--no-privileges \
> "${BACKUP_DIR}/superset_metadata.dump"
tar -czf "${BACKUP_DIR}/config.tar.gz" \
.env compose.yaml Dockerfile requirements-local.txt \
config/superset_config.py caddy/Caddyfile
docker run --rm \
-v superset_superset_home:/source:ro \
-v "${BACKUP_DIR}:/backup" \
alpine:3.20 \
tar -czf /backup/superset_home.tar.gz -C /source .
find "${BASE_DIR}/backups" -mindepth 1 -maxdepth 1 -type d -mtime +3 -exec rm -rf {} \;
export RESTIC_REPOSITORY="s3:s3.amazonaws.com/YOUR_BUCKET/superset"
export RESTIC_PASSWORD_FILE="/root/.config/restic/superset-password"
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
restic backup "${BACKUP_DIR}"
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
Перед использованием замените S3 endpoint, bucket и учётные данные. Не записывайте AWS_SECRET_ACCESS_KEY прямо в скрипт: лучше разместите переменные в root-доступном файле /root/.config/restic/superset-env с правами 600 и подключайте его через source.
Расписание cron и проверка восстановления
sudo crontab -e
30 2 * /opt/superset/scripts/backup.sh >> /var/log/superset-backup.log 2>&1
Бэкап будет запускаться ежедневно в 02:30. Не ограничивайтесь сообщением об успешном выполнении: раз в квартал поднимайте тестовый контейнер PostgreSQL и восстанавливайте дамп. Только успешное восстановление подтверждает, что резервная копия действительно пригодна.
docker compose exec -T db pg_restore \
-U superset \
-d superset \
--clean --if-exists \
< /path/to/superset_metadata.dump
Команду восстановления нельзя запускать на работающем production без окна обслуживания: она удалит и пересоздаст объекты metadata database. Проверяйте восстановление на отдельном тестовом стеке или временной базе.
Обновление Superset и контейнеров
Для одного VPS используйте maintenance window. Rolling update без простоя требует минимум двух экземпляров Superset за балансировщиком, совместимости миграций и отдельной стратегии Celery. Для небольшой инсталляции безопаснее сообщить о коротком окне обслуживания, сделать бэкап, обновить один компонент и выполнить smoke-test.
cd /opt/superset
./scripts/backup.sh
docker compose pull
docker compose build --pull
docker compose up -d
docker compose exec superset superset db upgrade
docker compose exec superset superset init
docker compose logs --tail=100 superset
docker compose ps
Не используйте тег latest для Superset в production: он может принести несовместимое изменение без явного решения администратора. Изменяйте SUPERSET_TAG в .env на конкретную протестированную версию, изучайте release notes и сначала повторяйте обновление в staging-среде.
Наблюдение за состоянием
Минимум раз в неделю проверяйте свободный диск, перезапуски контейнеров, размер PostgreSQL и логи ошибок. Диск, заполненный логами или PostgreSQL WAL, может привести к полной остановке базы данных.
cd /opt/superset
docker compose ps
docker stats --no-stream
docker system df
df -h
docker compose exec db psql -U superset -d superset -c \
"SELECT pg_size_pretty(pg_database_size('superset'));"
docker compose logs --since=24h superset | grep -iE "error|exception|traceback"
Не запускайте бездумно docker system prune -a на production-сервере: команда удаляет неиспользуемые образы и может осложнить быстрый откат. Используйте контролируемую очистку после подтверждения, что старые образы действительно не нужны.
Troubleshooting и FAQ
Почему Caddy не выпускает TLS-сертификат и в логах есть ACME error?
Сначала убедитесь, что A-запись домена указывает на IP VPS: dig +short superset.example.com должен вернуть адрес сервера. Затем проверьте, что UFW разрешает 80 и 443, а другой веб-сервер не занимает эти порты: sudo ss -ltnp | grep -E ':80|:443'. Также отключите проксирование DNS через CDN на время первого выпуска сертификата либо настройте DNS challenge. Посмотрите точную причину командой docker compose logs caddy.
Superset показывает 500 Internal Server Error после запуска. Что проверить?
Начните с логов: docker compose logs --tail=200 superset. Частые причины — неверный POSTGRES_PASSWORD, не применённые миграции, отсутствие SUPERSET_SECRET_KEY или синтаксическая ошибка в superset_config.py. Проверьте доступность базы через docker compose exec db pg_isready -U superset -d superset, затем повторите docker compose exec superset superset db upgrade и docker compose exec superset superset init. Не меняйте SECRET_KEY на уже работающей установке.
Почему контейнер worker постоянно перезапускается?
Посмотрите логи worker и Redis: docker compose logs --tail=200 worker redis. Обычно проблема вызвана неверным Redis URL, отсутствием Python-модуля, ошибкой в конфигурации Celery или нехваткой памяти. Проверьте docker stats --no-stream и системный журнал dmesg -T | grep -i oom. Если ядро завершило процесс через OOM killer, снизьте worker concurrency до -c 1, добавьте RAM или вынесите worker на отдельный сервер.
Подключение к PostgreSQL-источнику не проходит, хотя URI выглядит правильно. Как диагностировать?
Проверьте сетевую доступность из контейнера Superset, а не с локального компьютера: docker compose exec superset python -c "import socket; print(socket.gethostbyname('db-host'))". Убедитесь, что firewall источника разрешает IP VPS или приватную подсеть, а в pg_hba.conf есть подходящее правило. Затем проверьте пользователя напрямую через psql. Для внешнего PostgreSQL нужен отдельный read-only пользователь и разрешение CONNECT, USAGE и SELECT.
Почему дашборд работает медленно, хотя VPS почти не загружен?
Superset часто ожидает ответ от внешней БД, поэтому низкая загрузка VPS не означает нормальную производительность. Откройте SQL Lab, скопируйте сгенерированный запрос и выполните EXPLAIN ANALYZE на стороне источника. Добавьте индексы, создайте агрегированную витрину, materialized view или таблицу с предрасчётом. Уменьшите количество графиков на одной странице, настройте cache timeout и не выводите сотни тысяч строк в таблицах браузера.
Какой VPS-конфиг минимально подойдёт?
Для теста достаточно 2 vCPU, 4 ГБ RAM и 40–60 ГБ NVMe, но это компромисс: при запуске PostgreSQL, Redis, Superset и Celery память быстро заканчивается. Для реальной небольшой команды используйте минимум 4 vCPU, 8 ГБ RAM и 80–120 ГБ NVMe. Если источники данных внешние и запросы умеренные, этого достаточно для 5–30 активных пользователей. При регулярных отчётах и нескольких worker планируйте 16 ГБ RAM.
Что выбрать — VPS или dedicated для этой задачи?
VPS подходит почти всем небольшим и средним инсталляциям Superset, особенно когда аналитические данные находятся в отдельной базе, warehouse или managed-сервисе. Dedicated нужен при высоких требованиях к CPU, RAM, IOPS и изоляции: например, если на одном хосте работают Superset, ClickHouse и PostgreSQL с крупными наборами данных. Не переносите тяжёлую аналитическую БД на dedicated только потому, что Superset стал медленным: сначала профилируйте реальные SQL-запросы.
Можно ли открыть Superset напрямую на порту 8088?
Технически можно, но для production это плохая практика. Прямой доступ лишает вас автоматического TLS, централизованных HTTP-заголовков, нормальной обработки сертификатов и удобного ограничения трафика на reverse proxy. В Compose-файле порт 8088 намеренно не публикуется. Оставьте доступ только внутри Docker-сети и направляйте внешний трафик через Caddy. Если нужен временный локальный тест, используйте SSH port forwarding вместо открытия порта всему интернету.
Выводы и следующие шаги
Теперь Apache Superset работает на VPS в изолированном Docker-стеке с PostgreSQL, Redis, Celery и HTTPS через Caddy. Метаданные отделены от аналитических источников, доступ защищён TLS, а резервное копирование PostgreSQL можно выполнять автоматически.
- Создайте read-only технических пользователей для каждой подключаемой БД и ограничьте им доступ только нужными схемами и views.
- Настройте роли Superset, отключите лишние разрешения SQL Lab и протестируйте доступ обычного пользователя, а не только администратора.
- При росте нагрузки вынесите PostgreSQL metadata database в managed PostgreSQL, добавьте отдельные Celery worker и настройте мониторинг через Prometheus, Grafana или внешний uptime-check.
Перед крупным обновлением версии обязательно проверяйте миграции и восстановление бэкапа на тестовом сервере. Для стабильной аналитики важнее контролируемые изменения и права доступа к данным, чем максимальное число установленных компонентов.