MAATRIX / Блог / Как установить и настроить Apache APISIX на VPS

Как установить и настроить Apache APISIX на VPS

MAATRIX

Когда обычного Nginx с парой location уже не хватает — нужны динамические маршруты без перезагрузки конфига, rate limiting, JWT-авторизация и метрики из коробки — многие берут Kong или собирают самодельный слой на Lua-скриптах. Apache APISIX решает эту задачу проще: это API-шлюз на базе Nginx и LuaJIT (движок OpenResty), где маршруты и плагины настраиваются через REST API и хранятся в etcd, а не в текстовом конфиге. Дальше — рабочая установка на VPS через Docker Compose, первый маршрут, SSL и набор плагинов, которые реально нужны в проде.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое APISIX и когда он нужен вместо обычного Nginx

APISIX — это reverse proxy и API-шлюз с плагинной архитектурой. Технически он состоит из трёх частей:

  • Data plane — сам APISIX,worker-процессы на базе Nginx/OpenResty, которые реально проксируют трафик;
  • etcd — распределённое key-value хранилище, где лежит вся конфигурация (маршруты, апстримы, плагины). APISIX подписывается на изменения в etcd и применяет их без перезапуска;
  • Admin API — REST API (порт 9180 по умолчанию), через который вы создаёте и меняете маршруты. Веб-интерфейса из коробки нет — для UI ставится отдельный компонент apisix-dashboard.

Смысл появляется, когда у вас не один сайт, а несколько бэкендов (микросервисы, мобильный API, партнёрские интеграции), и маршруты меняются чаще, чем раз в месяц. Задача «добавить новый эндпоинт с лимитом запросов и JWT-проверкой» в APISIX — это один POST-запрос к Admin API, без nginx -s reload и без риска уронить конфиг опечаткой в location.

Если у вас один сайт с парой апстримов и конфигурация меняется редко — переплата: проще и надёжнее взять Nginx как reverse proxy. APISIX стоит ставить, когда динамика маршрутов и плагины перевешивают сложность лишнего etcd в стеке.

Требования к серверу и подготовка

APISIX сам по себе лёгкий (сборка на Nginx съедает немного памяти на старте), но etcd под нагрузкой любит iops и не любит своп. Ориентир для продакшена:

ПараметрМинимумКомфортно
CPU1 vCPU2 vCPU
RAM1 GB2-4 GB
Диск15 GB SSD30+ GB NVMe
ОСUbuntu 24.04 / Debian 12Ubuntu 24.04

На 1 GB RAM APISIX и однонодовый etcd поднимутся и будут работать, но при активной записи в etcd (частое создание маршрутов, большие ACL-списки) лучше закладывать 2 GB — иначе etcd может начать спотыкаться о OOM killer.

Перед установкой:

apt update && apt upgrade -y
apt install -y curl ca-certificates gnupg

Docker и Docker Compose — обязательны, вся установка ниже собрана вокруг них. Заодно откройте нужные порты в фаерволе — как минимум 80/443 наружу и 9180 (Admin API) только с доверенных IP, это лучше сделать через ufw сразу после установки Docker.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Установка через Docker Compose

Официальный путь для продакшена — Helm на Kubernetes, но для одиночного VPS Docker Compose проще и вполне жизнеспособен: он же используется в quickstart-сценариях самого проекта. Поднимаем три контейнера: etcd, apisix и apisix-dashboard.

mkdir -p /opt/apisix && cd /opt/apisix
mkdir -p apisix_log apisix_conf dashboard_conf etcd_data

Файл docker-compose.yml:

version: "3"

services:
  etcd:
    image: bitnami/etcd:3.5
    restart: unless-stopped
    environment:
      ETCD_ENABLE_V2: "true"
      ALLOW_NONE_AUTHENTICATION: "yes"
      ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379"
      ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
    volumes:
      - ./etcd_data:/bitnami/etcd
    networks:
      - apisix

  apisix:
    image: apache/apisix:3.9.1-debian
    restart: unless-stopped
    depends_on:
      - etcd
    volumes:
      - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
      - ./apisix_log:/usr/local/apisix/logs
    ports:
      - "9080:9080"   # HTTP data plane
      - "9443:9443"   # HTTPS data plane
      - "9180:9180"   # Admin API
    networks:
      - apisix

  dashboard:
    image: apache/apisix-dashboard:3.0.1-alpine
    restart: unless-stopped
    depends_on:
      - apisix
    volumes:
      - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml:ro
    ports:
      - "9000:9000"
    networks:
      - apisix

networks:
  apisix:
    driver: bridge

Версии образов (3.9.1, 3.0.1) — ориентир на момент написания, перед установкой сверьтесь с актуальными тегами на Docker Hub, APISIX выпускает релизы регулярно.

Файл apisix_conf/config.yaml — минимум для работы с внешним etcd и своим ключом Admin API:

deployment:
  admin:
    allow_admin:
      - 0.0.0.0/0        # на проде замените на реальные доверенные IP
    admin_key:
      - name: "admin"
        key: "ЗАМЕНИТЕ_НА_СЛУЧАЙНУЮ_СТРОКУ_32+_СИМВОЛА"
        role: admin
  etcd:
    host:
      - "http://etcd:2379"
    prefix: "/apisix"
    timeout: 30

Файл dashboard_conf/conf.yaml:

conf:
  listen:
    host: 0.0.0.0
    port: 9000
  etcd:
    endpoints:
      - etcd:2379
authentication:
  secret: "ЗАМЕНИТЕ_НА_ДРУГУЮ_СЛУЧАЙНУЮ_СТРОКУ"
  expire_time: 3600
  users:
    - username: admin
      password: "ЗАМЕНИТЕ_НА_НАДЁЖНЫЙ_ПАРОЛЬ"

Ключ admin_key продублируйте один в один в обоих файлах ниже, где это нужно, и никогда не оставляйте дефолтный edd1c9f034335f136f87ad84b625c8f из официальных примеров — по нему в интернете сканируют открытые Admin API пачками.

Запуск:

docker compose up -d
docker compose ps

Проверка, что data plane жив:

curl -i http://127.0.0.1:9080/apisix/status

Дашборд будет на http://IP-сервера:9000 — до настройки SSL и ограничения доступа держите порт 9000 закрытым для внешнего мира через ufw и заходите только через SSH-туннель (ssh -L 9000:localhost:9000 user@server).

Первый маршрут и Admin API

Маршруты (routes) и апстримы (upstreams) создаются через Admin API. Заведём апстрим на локальный сервис (например, приложение на порту 3000) и маршрут к нему:

curl -i "http://127.0.0.1:9180/apisix/admin/routes/1" \
  -H "X-API-KEY: ЗАМЕНИТЕ_НА_СЛУЧАЙНУЮ_СТРОКУ_32+_СИМВОЛА" \
  -X PUT -d '
{
  "uri": "/api/*",
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "127.0.0.1:3000": 1
    }
  }
}'

Проверяем:

curl -i "http://127.0.0.1:9080/api/health"

Если бэкенд слушает на 3000 и отвечает — запрос через 9080 дойдёт до него, минуя прямой доступ к порту (который стоит закрыть в ufw). Для нескольких бэкендов апстрим можно вынести отдельным объектом и переиспользовать в разных маршрутах:

curl -i "http://127.0.0.1:9180/apisix/admin/upstreams/backend-app" \
  -H "X-API-KEY: ЗАМЕНИТЕ_НА_СЛУЧАЙНУЮ_СТРОКУ_32+_СИМВОЛА" \
  -X PUT -d '
{
  "type": "roundrobin",
  "nodes": {
    "10.0.0.11:3000": 1,
    "10.0.0.12:3000": 1
  }
}'

Дальше маршрут ссылается на него через "upstream_id": "backend-app" вместо инлайн-объекта — удобно, когда за одним апстримом несколько маршрутов.

SSL и домены

За TLS-терминацию отвечает сам APISIX (порт 9443), сертификат подгружается тоже через Admin API, а не через файлы в /etc/nginx/. Если у вас уже есть сертификат от Let's Encrypt (например, выпущенный certbot'ом отдельно с DNS-валидацией, без занятого 80-го порта), загружаем его так:

curl -i "http://127.0.0.1:9180/apisix/admin/ssls/1" \
  -H "X-API-KEY: ЗАМЕНИТЕ_НА_СЛУЧАЙНУЮ_СТРОКУ_32+_СИМВОЛА" \
  -X PUT -d '
{
  "cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
  "key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
  "snis": ["api.example.com"]
}'

Переносить содержимое .pem-файлов в JSON руками неудобно — проще собрать запрос скриптом, который читает файлы и подставляет их через jq:

CERT=$(cat /etc/letsencrypt/live/api.example.com/fullchain.pem)
KEY=$(cat /etc/letsencrypt/live/api.example.com/privkey.pem)

jq -n --arg cert "$CERT" --arg key "$KEY" \
  '{cert: $cert, key: $key, snis: ["api.example.com"]}' | \
curl -i "http://127.0.0.1:9180/apisix/admin/ssls/1" \
  -H "X-API-KEY: ЗАМЕНИТЕ_НА_СЛУЧАЙНУЮ_СТРОКУ_32+_СИМВОЛА" \
  -X PUT -d @-

Продление Let's Encrypt происходит отдельно от APISIX — certbot обновляет файлы на диске, а вам нужен хук, который после renew перезаливает сертификат в etcd тем же запросом (обычный deploy-hook в конфиге certbot). Автоматического подхвата обновлённого файла с диска, как у Nginx с ssl_certificate, здесь нет — это одно из ограничений APISIX, о котором стоит знать заранее.

Плагины: лимиты, авторизация, метрики

Плагины включаются per-route прямо в теле маршрута, без отдельных модулей. Три самых востребованных в проде:

Rate limiting — защита от перебора и грубого DDoS на уровне приложения:

"plugins": {
  "limit-req": {
    "rate": 10,
    "burst": 5,
    "key_type": "var",
    "key": "remote_addr"
  }
}

JWT-авторизация — проверка токена на входе, без своей логики в бэкенде:

"plugins": {
  "jwt-auth": {}
}

Для jwt-auth сначала нужно создать consumer с секретом через /apisix/admin/consumers, а уже клиент присылает токен, подписанный этим секретом.

Prometheus — экспорт метрик по каждому маршруту (RPS, латентность, коды ответов):

"plugins": {
  "prometheus": {}
}

После включения метрики доступны на http://127.0.0.1:9091/apisix/prometheus/metrics (порт настраивается) — их можно скрейпить тем же Prometheus, что уже собирает метрики с других контейнеров вашего стека.

Полный список плагинов (IP restriction, CORS, request-id, proxy-cache, cache, opentelemetry и другие) смотрите в документации проекта — набор регулярно пополняется, и версии плагинов привязаны к версии образа apache/apisix.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Чем APISIX лучше обычного Nginx для API?

Тем, что маршруты, upstream'ы и плагины меняются через REST API без перезагрузки процесса и без риска сломать текстовый конфиг опечаткой. Для статичного набора из пары location'ов разница не критична — там проще Nginx как reverse proxy.

Обязателен ли etcd, нельзя ли обойтись без него?

Начиная с APISIX есть standalone-режим с конфигурацией из YAML-файла (без etcd), но он теряет главное преимущество — динамические изменения без перезапуска. Для прода с активно меняющимися маршрутами держат etcd, для простого статичного шлюза standalone-режим может быть избыточен по сложности установки ради того же результата, что даёт Nginx.

APISIX и Kong — в чём разница?

Оба — плагинные API-шлюзы поверх Nginx/OpenResty. Kong традиционно использует PostgreSQL или свой DB-less режим, APISIX — etcd. Разница на практике чаще всего в наборе плагинов и личных предпочтениях команды; если уже пробовали Kong Gateway в Docker Compose, сравнение будет нагляднее на своих задачах.

Как защитить Admin API от посторонних?

Три вещи обязательны: сменить дефолтный admin_key, ограничить allow_admin реальными IP (а не 0.0.0.0/0, как в примере выше для локальной отладки) и закрыть порт 9180 в ufw для всех, кроме доверенных адресов.

Нужен ли отдельный VPS под APISIX или можно на том же сервере, где бэкенд?

Можно на одном — легковесная связка APISIX + однонодовый etcd на 2 vCPU / 2-4 GB RAM спокойно уживается с несколькими бэкенд-контейнерами. Разносить стоит, когда трафик через шлюз растёт настолько, что нагрузка от etcd (диск, iops) начинает мешать основным сервисам.

Что делать, если etcd упал?

APISIX держит в памяти последнюю применённую конфигурацию и продолжает проксировать трафик по ней, но новые изменения через Admin API применяться не будут, пока etcd не поднимется обратно. Резервное копирование данных etcd (папка etcd_data в примере выше) — обязательная часть плана бэкапов, как и для любого stateful-контейнера.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →