Оригинал: Arkeep — Централизованный Backup-сервер с агентами, на базе Restic и Rclone — Иван Чёрный, 23 июня 2026. Лицензия CC BY-NC-SA 4.0 . Публикуется с сохранением авторства и лицензии.

Предисловие

Arkeep — open-source система централизованного резервного копирования на основе Restic и Rclone. Проект решает проблему отсутствия полноценно централизованного инструмента бэкапа в экосистеме Open Source.

Архитектура построена по принципу сервер-агент: администратор разворачивает сервер Arkeep, ставит агенты на нужные хосты и управляет резервным копированием из единой панели. В качестве хранилища поддерживаются все решения, совместимые с Restic и Rclone (40+ провайдеров).

На момент написания проект активно развивается, возможны изменения в конфигурации и баги.

Схема резервного копирования

Настраиваем бэкап серверов на Debian 13 с помощью Arkeep в S3-хранилище RustFS. Доступ ко всем ресурсам — через обратный прокси Angie с автоматическими TLS-сертификатами Let’s Encrypt.

Важно: Web GUI работает по HTTP/HTTPS, агенты подключаются отдельно по gRPC. Взаимодействие агентов и сервера настраивается через проксирование gRPC (grpc_pass).

Вводные данные

ПОВерсия
Debian13
Docker Engine28
Angie1.9.1
Arkeep0.4.5
RustFS1.0.0-beta.8

Доменная схема:

Установка бэкап-сервера Arkeep

Подключаемся по SSH и переходим на root:

BASH
ssh ivan@arkeep.r4ven.me
sudo -i
Нажмите, чтобы развернуть и увидеть больше

Создаём Docker-сеть:

BASH
docker network create --opt com.docker.network.bridge.name=br-arkeep --opt com.docker.network.enable_ipv6=false --driver bridge --subnet 172.20.20.0/24 --gateway 172.20.20.1 arkeep_net
Нажмите, чтобы развернуть и увидеть больше

Создаём директорию проекта:

BASH
install -m 700 -d /etc/compose
mkdir -vp /etc/compose/arkeep && cd /etc/compose/arkeep
Нажмите, чтобы развернуть и увидеть больше

compose.yaml:

YAML
---
# https://github.com/arkeep-io/arkeep/tree/main/deploy/docker

networks:
  arkeep_net:
    external: true

volumes:
  arkeep_server:
    name: arkeep_server
  arkeep_agent:
    name: arkeep_agent

services:
  arkeep_server:
    image: ghcr.io/arkeep-io/arkeep-server:v0.4.5
    container_name: arkeep-server
    restart: unless-stopped
    stop_grace_period: 1m
    cpus: 1
    mem_limit: 1G
    hostname: arkeep-server
    env_file: ./.env
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health/ready"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    expose:
      - "8080"   # REST API + GUI
      - "9090"   # gRPC (agents)
    volumes:
      - arkeep_server:/var/lib/arkeep/
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    networks:
      - arkeep_net

  arkeep_agent:
    image: ghcr.io/arkeep-io/arkeep-agent:v0.4.5
    depends_on:
      arkeep_server:
        condition: service_healthy
    container_name: arkeep-agent
    restart: unless-stopped
    stop_grace_period: 1m
    cpus: 1
    mem_limit: 1G
    hostname: arkeep-agent
    environment:
      TZ: "${TZ:-Europe/Moscow}"
      ARKEEP_SERVER_ADDR: "arkeep-server:9090"
      ARKEEP_AGENT_SECRET: "${ARKEEP_AGENT_SECRET}"
      ARKEEP_STATE_DIR: "/var/lib/arkeep-agent"
      ARKEEP_LOG_LEVEL: "${ARKEEP_LOG_LEVEL:-info}"
      ARKEEP_GRPC_INSECURE: "${ARKEEP_GRPC_INSECURE:-false}"
    volumes:
      - arkeep_agent:/var/lib/arkeep-agent/
      - /:/hostfs/:ro # :ro for backup-only; change to :rw to also restore to local paths
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /var/lib/docker/volumes/:/var/lib/docker/volumes/:ro
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    networks:
      - arkeep_net
Нажмите, чтобы развернуть и увидеть больше

Монтирование корня ФС /:/hostfs/:ro в режиме только для чтения позволяет делать бэкапы. Для восстановления нужно поменять :ro на :rw.

.env:

INI
# https://github.com/arkeep-io/arkeep/tree/main/deploy/docker

TZ=Europe/Moscow
ARKEEP_SECRET_KEY=
ARKEEP_AGENT_SECRET=
ARKEEP_DATA_DIR=/var/lib/arkeep/data
ARKEEP_DB_DRIVER=sqlite
ARKEEP_DB_DSN=/var/lib/arkeep/arkeep.db
ARKEEP_LOG_LEVEL=info
ARKEEP_SERVER_ADDR=arkeep-grpc.r4ven.me:443
ARKEEP_SERVER_HTTP_ADDR=https://arkeep.r4ven.me
ARKEEP_GRPC_INSECURE=true
ARKEEP_TELEMETRY=true
Нажмите, чтобы развернуть и увидеть больше

Параметры:

ARKEEP_AGENT_SECRET должен совпадать на сервере и всех агентах.

Генерируем секреты:

BASH
sed -iE "s/^ARKEEP_SECRET_KEY=.*/ARKEEP_SECRET_KEY=$(openssl rand -hex 32)/" ./.env
sed -iE "s/^ARKEEP_AGENT_SECRET=.*/ARKEEP_AGENT_SECRET=$(openssl rand -hex 24)/" ./.env
Нажмите, чтобы развернуть и увидеть больше

Запускаем стек и настраиваем автозапуск:

BASH
docker compose up -d && docker compose logs -f
Нажмите, чтобы развернуть и увидеть больше
BASH
cat > ./arkeep.service << EOF
[Unit]
Description=Arkeep service
Requires=docker.service
After=docker.service

[Service]
Restart=always
RestartSec=5
User=root
Group=root
WorkingDirectory=$(realpath ./)
ExecStart=/usr/bin/docker compose up --remove-orphans
ExecStop=/usr/bin/docker compose down

[Install]
WantedBy=multi-user.target
EOF

chmod 600 ./arkeep.service
ln -s $(realpath ./arkeep.service) /etc/systemd/system
systemctl daemon-reload
systemctl enable --now arkeep
systemctl status arkeep
Нажмите, чтобы развернуть и увидеть больше

Установка S3-хранилища RustFS

Подробно установка и настройка RustFS разобрана в отдельной статье. Здесь — вариант для этой инсталляции (в общей сети arkeep_net).

BASH
mkdir -vp /etc/compose/rustfs && cd /etc/compose/rustfs
Нажмите, чтобы развернуть и увидеть больше

compose.yaml:

YAML
---
# https://github.com/rustfs/rustfs

networks:
  arkeep_net:
    external: true

volumes:
  rustfs:
    name: rustfs

services:
  rustfs:
    image: rustfs/rustfs:1.0.0-beta.8
    container_name: rustfs
    restart: unless-stopped
    stop_grace_period: 30s
    cpus: 1
    mem_limit: 1G
    hostname: rustfs
    env_file: ./.env
    healthcheck:
      test:
        ["CMD", "sh", "-c", "curl -f http://127.0.0.1:9000/health && curl -f http://127.0.0.1:9001/rustfs/console/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    expose:
      - "9000" # S3 API port
      - "9001" # Console port
    volumes:
      - rustfs:/data/
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    networks:
      - arkeep_net
Нажмите, чтобы развернуть и увидеть больше

.env:

INI
# https://docs.rustfs.com/installation/docker/#complete-parameter-configuration-example

TZ=Europe/Moscow
# RUSTFS_VOLUMES=/data/rustfs{0..3} # Define 4 storage volumes
RUSTFS_ADDRESS=0.0.0.0:9000
RUSTFS_CONSOLE_ENABLE=true
RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001
RUSTFS_CORS_ALLOWED_ORIGINS=https://rustfs.r4ven.me
RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS=https://rustfs.r4ven.me
RUSTFS_ACCESS_KEY=
RUSTFS_SECRET_KEY=
RUSTFS_OBS_LOGGER_LEVEL=info
Нажмите, чтобы развернуть и увидеть больше

Устанавливаем учётные данные, запускаем и настраиваем автозапуск (аналогично серверу Arkeep):

BASH
sed -iE "s/^RUSTFS_ACCESS_KEY=.*/RUSTFS_ACCESS_KEY=ivan/" ./.env
sed -iE "s/^RUSTFS_SECRET_KEY=.*/RUSTFS_SECRET_KEY=$(openssl rand -hex 32)/" ./.env

docker compose up -d && docker compose logs -f
Нажмите, чтобы развернуть и увидеть больше
BASH
cat > ./rustfs.service << EOF
[Unit]
Description=RustFS S3 service
Requires=docker.service
After=docker.service

[Service]
Restart=always
RestartSec=5
User=root
Group=root
WorkingDirectory=$(realpath ./)
ExecStart=/usr/bin/docker compose up --remove-orphans
ExecStop=/usr/bin/docker compose down

[Install]
WantedBy=multi-user.target
EOF

chmod 600 ./rustfs.service
ln -s $(realpath ./rustfs.service) /etc/systemd/system
systemctl daemon-reload
systemctl enable --now rustfs
systemctl status rustfs
Нажмите, чтобы развернуть и увидеть больше

Установка обратного прокси Angie

BASH
mkdir -vp /etc/compose/angie && cd /etc/compose/angie
Нажмите, чтобы развернуть и увидеть больше

compose.yaml:

YAML
---
# https://angie.software/angie/docs/installation/docker/

networks:
  arkeep_net:
    external: true

services:
  angie:
    image: docker.angie.software/angie:1.9.1-alpine
    container_name: angie
    restart: unless-stopped
    stop_grace_period: 1m
    cpus: 1
    mem_limit: 1G
    hostname: angie
    environment:
      TZ: Europe/Moscow
    volumes:
      - ./config/angie.conf:/etc/angie/angie.conf:ro
      - ./config/http.d/:/etc/angie/http.d/:ro
      - ./certs/:/var/lib/angie/acme/
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "80:80/tcp"
      - "443:443/tcp"
      - "443:443/udp"
    networks:
      - arkeep_net
Нажмите, чтобы развернуть и увидеть больше

Создаём директорию конфигов и основной конфиг config/angie.conf:

BASH
mkdir -vp ./config
Нажмите, чтобы развернуть и увидеть больше
NGINX
user angie;
worker_processes auto;
worker_rlimit_nofile 65536;

error_log /var/log/angie/error.log notice;
pid /run/angie/angie.pid;

events {
    worker_connections 65536;
}

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    include /etc/angie/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/angie/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 20;
    keepalive_requests 1000;

    server_tokens off;

    # DNS resolver for ACME.
    resolver 8.8.8.8 8.8.4.4 ipv6=off valid=300s;

    acme_client le https://acme-v02.api.letsencrypt.org/directory
        email=kar-kar@r4ven.me
        key_type=ecdsa
        renew_before_expiry=30d
    ;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    upstream arkeep_server {
        server arkeep-server:9090;
    }

    upstream arkeep_console {
        server arkeep-server:8080;
    }

    upstream rustfs_server {
        server rustfs:9000;
    }

    upstream rustfs_console {
        server rustfs:9001;
    }

    server {
        listen 80;

        server_name
            arkeep-grpc.r4ven.me
            arkeep.r4ven.me
            rustfs-s3.r4ven.me
            rustfs.r4ven.me
        ;

        location /.well-known/acme-challenge/ {
            root /usr/share/angie/html/;
        }

        location / {
            return 301 https://$host$request_uri;
        }
    }

    server {
        listen 443 ssl;

        http2 on;
        http3 on;

        server_name arkeep-grpc.r4ven.me;

        acme le;

        ssl_certificate $acme_cert_le;
        ssl_certificate_key $acme_cert_key_le;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;

        location / {
            grpc_pass grpc://arkeep_server;

            grpc_set_header Host $host;
            grpc_set_header X-Real-IP $remote_addr;
            grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            grpc_connect_timeout 10s;
            grpc_send_timeout 1h;
            grpc_read_timeout 1h;

            grpc_socket_keepalive on;
        }
    }

    server {
        listen 443 ssl;

        http2 on;
        http3 on;

        server_name arkeep.r4ven.me;

        acme le;

        ssl_certificate $acme_cert_le;
        ssl_certificate_key $acme_cert_key_le;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;

        client_max_body_size 0;

        location / {
            proxy_pass http://arkeep_console;

            proxy_http_version 1.1;
            proxy_request_buffering off;
            proxy_buffering off;

            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_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Port 443;
            proxy_set_header X-Forwarded-Ssl on;

            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            proxy_connect_timeout 10s;
            proxy_send_timeout 1h;
            proxy_read_timeout 1h;
        }
    }

    server {
        listen 443 ssl;

        http2 on;
        http3 on;

        server_name rustfs-s3.r4ven.me;

        acme le;

        ssl_certificate $acme_cert_le;
        ssl_certificate_key $acme_cert_key_le;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;

        client_max_body_size 0;

        location / {
            proxy_pass http://rustfs_server;

            proxy_http_version 1.1;
            proxy_request_buffering off;
            proxy_buffering off;
            proxy_cache off;
            proxy_max_temp_file_size 0;

            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_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Port 443;
            proxy_set_header X-Forwarded-Ssl on;

            proxy_connect_timeout 10s;
            proxy_send_timeout 1h;
            proxy_read_timeout 1h;
        }
    }

    server {
        listen 443 ssl;

        http2 on;
        http3 on;

        server_name rustfs.r4ven.me;

        acme le;

        ssl_certificate $acme_cert_le;
        ssl_certificate_key $acme_cert_key_le;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;

        location / {
            proxy_pass http://rustfs_console;

            proxy_http_version 1.1;

            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_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }

    include /etc/angie/http.d/*.conf;
}
Нажмите, чтобы развернуть и увидеть больше

Обязательно замените email= и значения server_name под свои домены.

Запускаем и настраиваем автозапуск:

BASH
docker compose up -d && docker compose logs -f
Нажмите, чтобы развернуть и увидеть больше
BASH
cat > ./angie.service << EOF
[Unit]
Description=Angie proxy service
Requires=docker.service
After=docker.service

[Service]
Restart=always
RestartSec=5
User=root
Group=root
WorkingDirectory=$(realpath ./)
ExecStart=/usr/bin/docker compose up --remove-orphans
ExecStop=/usr/bin/docker compose down

[Install]
WantedBy=multi-user.target
EOF

chmod 600 ./angie.service
ln -s $(realpath ./angie.service) /etc/systemd/system
systemctl daemon-reload
systemctl enable --now angie
systemctl status angie
Нажмите, чтобы развернуть и увидеть больше

Установка агентов Arkeep на app-серверах

Переходим на хосты для бэкапа (app1.r4ven.me, app2.r4ven.me, …).

BASH
install -m 700 -d /etc/compose
mkdir -vp /etc/compose/arkeep_agent && cd /etc/compose/arkeep_agent
Нажмите, чтобы развернуть и увидеть больше

compose.yaml:

YAML
---
# https://github.com/arkeep-io/arkeep/tree/main/deploy/docker

volumes:
  arkeep_agent:
    name: arkeep_agent

services:
  arkeep_agent:
    image: ghcr.io/arkeep-io/arkeep-agent:v0.4.5
    container_name: arkeep-agent-app1
    restart: unless-stopped
    stop_grace_period: 1m
    cpus: 1
    mem_limit: 1G
    hostname: arkeep-agent-app1
    env_file: ./.env
    volumes:
      - arkeep_agent:/var/lib/arkeep-agent/
      - /:/hostfs/:ro # :ro for backup-only; change to :rw to also restore to local paths
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /var/lib/docker/volumes/:/var/lib/docker/volumes/:ro
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
Нажмите, чтобы развернуть и увидеть больше

Bind mount /hostfs даёт агенту доступ к ФС хоста. Режим ro достаточен для бэкапов; для восстановления нужен rw.

.env:

INI
# https://github.com/arkeep-io/arkeep/tree/main/deploy/docker

TZ=Europe/Moscow
ARKEEP_SERVER_ADDR=arkeep-grpc.r4ven.me:443
ARKEEP_SERVER_HTTP_ADDR=https://arkeep.r4ven.me
ARKEEP_AGENT_SECRET=
ARKEEP_STATE_DIR=/var/lib/arkeep-agent
ARKEEP_LOG_LEVEL=info
ARKEEP_GRPC_INSECURE=false
Нажмите, чтобы развернуть и увидеть больше

ARKEEP_AGENT_SECRET должен совпадать со значением на сервере. ARKEEP_GRPC_INSECURE=false — TLS до Angie, затем без шифрования.

Запускаем:

BASH
docker compose up -d && docker compose logs -f
Нажмите, чтобы развернуть и увидеть больше

При успешном подключении в логах:

PLAINTEXT
arkeep-agent-app1  | {"level":"info", ... "msg":"registered with server","agent_id":"019ebc8e-...","agent_name":"arkeep-agent-app1"}
arkeep-agent-app1  | {"level":"info", ... "msg":"job stream open","agent_id":"019ebc8e-..."}
Нажмите, чтобы развернуть и увидеть больше

Автозапуск — по той же схеме, что и для сервера (arkeep-agent.service).

Настройка Arkeep

Destination — S3

Web GUI на https://arkeep.r4ven.me → «Destinations» → «New Destination» → тип «S3/Object Storage». Указываем имя бакета и реквизиты (endpoint = rustfs-s3.r4ven.me, access_key_id, secret_access_key для бакета с политикой readwrite).

Помимо S3 бэкапы можно сохранять в локальную директорию, по SFTP, в REST Server или в любое удалённое хранилище через Rclone (40+ провайдеров). Для Rclone в контейнер нужно доустановить rclone и примонтировать конфиг:

BASH
cat > ./rclone.conf << EOF
[webdav-backup]
type = webdav
url = https://cloud.example.com/remote.php/dav/files/USER
vendor = nextcloud
user = USER
pass = OBSCURED_PASSWORD
EOF
Нажмите, чтобы развернуть и увидеть больше
YAML
---
services:
  arkeep_agent:
    image: ghcr.io/arkeep-io/arkeep-agent:v0.4.5
    container_name: arkeep-agent-rclone
    restart: unless-stopped
    hostname: arkeep-agent-rclone
    env_file: ./.env
    command: sh -c 'apk add rclone; exec arkeep-agent'
    volumes:
      - ./data/:/var/lib/arkeep-agent/
      - /:/hostfs/:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /var/lib/docker/volumes/:/var/lib/docker/volumes/:ro
      - ./rclone.conf:/root/.config/rclone/rclone.conf:ro
Нажмите, чтобы развернуть и увидеть больше

Policy

«Policies» → «New Policy». Указываем имя задания, агента, пароль для шифрования, источники бэкапа (например, /etc и Docker volumes), расписание в формате crontab и время хранения. Выбираем S3-destination и, при необходимости, исключения.

Для расчёта расписания удобен crontab.guru .

Запуск и восстановление

Проверка — кнопка «Run» в Web GUI. Успешный бэкап появится в «Snapshots», а в S3 — файлы репозитория Restic.

Для восстановления по умолчанию ФС хоста монтируется :ro. Меняем на :rw в compose.yaml и перезапускаем агента:

BASH
systemctl restart arkeep-agent
Нажмите, чтобы развернуть и увидеть больше

Далее «Snapshots» → выбираем бэкап → «Restore». Доступны режимы:

Возможные проблемы

read only filesystem — директория назначения недоступна для записи. Смените :ro:rw.

enrollment failed (server returned 405 Method Not Allowed) — при ARKEEP_GRPC_INSECURE=true механизм enrollment не используется; ошибку можно игнорировать, если агент подключается по gRPC (registered with server, job stream open).

failed to verify certificate (x509: certificate signed by unknown authority) — не указан ARKEEP_SERVER_HTTP_ADDR, агент идёт не на тот hostname, самоподписанный сертификат, либо TLS включён/выключен только на одной стороне.

certificate is valid for arkeep-grpc, not arkeep.r4ven.me — остановите сервер, удалите Docker volume с данными, перезапустите — сертификаты переиздадутся.

Про телеметрию

Arkeep раз в день собирает анонимную телеметрию (ID инстанса, версия, ОС, число агентов и политик). Личные данные, содержимое бэкапов и учётные данные не передаются. Отключается через ARKEEP_TELEMETRY=false. Статистика — на telemetry.arkeep.io/stats .

Послесловие

Arkeep — удобный инструмент резервного копирования с большим потенциалом. Идея использования Restic и Rclone проста и эффективна. По ходу написания оригинала автор завёл два issue (#158 , #159 ) — разработчик оперативно исправил оба бага в 0.4.5.

Используемые материалы

Авторские права

Автор: Vasiliy Fakunin

Ссылка: https://notes.melancholic.tech/posts/arkeep-backup-server/

Лицензия: CC BY-NC-SA 4.0

Использование материалов блога разрешается при условии: указания авторства/источника, некоммерческого использования и сохранения лицензии.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша