Управление клиентами AmneziaWG из командной строки

amneziawg-installer ставит AmneziaWG 2.0 на Ubuntu и Debian. Клиентами дальше занимается скрипт manage_amneziawg.sh: завести, удалить, перевыпустить конфиг, выдать QR-код или vpn://-ссылку. Он же показывает статистику, делает бэкапы и чинит модуль ядра после обновления. Всё это одной командой по SSH, а для скриптов и ботов есть вывод в JSON.

Типовые задачи

Ниже только подкоманды, полный вызов выглядит так: sudo bash /root/awg/manage_amneziawg.sh <команда>.

ЗадачаКоманда
Завести телефон и получить QR-кодadd phone
Добавить три устройства разомadd phone laptop tablet
Дать гостю доступ на неделюadd guest --expires=7d
Отозвать доступremove guest
Посмотреть, кто подключён и сколько скачалstats
Перевыпустить конфиг после потери телефонаregen phone
Сделать бэкап перед любыми правкамиbackup
Вернуть туннель после обновления ядраrepair-module

Все команды одной таблицей

Установщик кладёт скрипт на сервер сам, запускать его нужно от root. Столбец JSON показывает, что вернёт флаг --json.

КомандаЧто делаетJSON
add <имя> [имя2 ...]Заводит клиента: ключи, конфиг, QR-код и vpn://-ссылка. Имён можно несколько сразу. --expires= выдаёт доступ на время, --psk добавляет PresharedKey.объект
remove <имя> [имя2 ...]Удаляет клиента и отзывает доступ. Имён можно несколько сразу.объект
listСписок клиентов. С -v подробнее; в JSON-виде есть ещё адрес IPv6 и машинный статус.массив
statsТрафик по каждому клиенту и время последнего хендшейка.массив
regen [имя ...]Перевыпускает файлы клиента, сохраняя ключи и адрес. --reset-routes сбрасывает маршрутизацию к текущему режиму.объект
modify <имя> <параметр> <значение>Меняет отдельный параметр клиента.объект
backupСоздаёт резервную копию конфигурации сервера и набора клиентов.объект
restore [файл]Восстанавливает из копии и сообщает, был ли откат.объект
checkСостояние сервера: модуль, сервис, порт, файрвол. Алиас: status.объект
diagnoseСамодиагностика: ядро, sysctl и UFW, а с --carrier= ещё и сверка обфускации с профилем мобильного оператора.только текст
showСырой вывод awg show.только текст
restartПерезапускает сервис AmneziaWG.объект
repair-moduleПересобирает модуль ядра после обновления ядра и возвращает туннель. Алиас: repair.объект
helpПолная справка со всеми флагами.только текст

Срок для временного доступа пишется как Nh, Nd или Nw: 12h, 7d, 4w. Cron проверяет сроки каждые пять минут и снимает просроченных, вручную чистить ничего не нужно.

Машинный вывод для скриптов и ботов

Начиная с v5.21.0 команды управления понимают --json. Флаг нужен ровно для того, чтобы боту не приходилось разбирать человеческий текст и гадать, сработала команда или нет.

Ровно один JSON-документ

У команды, которая понимает флаг, на stdout приходит ровно один JSON-документ за запуск, при любом исходе, включая аварийное завершение и отказ от подтверждения. Команды с конвертом отдают объект, list и stats - голый массив. Человеческие сообщения уходят в stderr, потоки не смешиваются.

Источник истины - код возврата

Поле ok дублирует его для ботов, которые читают только stdout. Частичный отказ считается отказом: add a b, где b уже существует, вернёт ok:false.

Схема только расширяется

Новые поля со временем появляются, существующие не переименовываются и не меняют тип. list и stats остаются голыми массивами, какими и были.

Подтверждение и неинтерактивный запуск

--json не подразумевает --yes - это независимые флаги. Но рассчитывать на подтверждение как на защиту нельзя: когда терминала нет, спросить некого, и деструктивная команда выполняется молча. Чтобы такой запуск отклонялся, а не проходил, включайте AWG_STRICT_CONFIRM=1 - тогда remove без --yes вернёт отказ с rc 1.

Успешное выполнение add:

{"command":"add","ok":true,"added":1,"failed":0,"applied":true,
 "results":[{"name":"phone","status":"created","conf":"/root/awg/phone.conf",
             "qr":"/root/awg/phone.png","vpnuri":"/root/awg/phone.vpnuri","expires_at":null}]}

Любой сбой, включая прерванное подтверждение:

{"command":"remove","ok":false,"error":"confirmation denied","rc":1}

Поле error - человекочитаемый текст, он бывает локализован. Машинные решения принимаются по ok, rc и status. Две ловушки. Первая: repair-module.rc - это внутренний код проверки модуля, а не код возврата процесса. Вторая: ошибка в аргументах тоже приходит конвертом, и в поле command окажется либо help, либо сама неизвестная команда, а не одно из 14 канонических имён. Алиасы приводятся к канону: в ответе всегда check и repair-module, как бы команду ни набрали.

Машинные статусы клиента

Поле status_code есть и в list --json, и в stats --json. В отличие от статуса для человека, эти значения не зависят от языка скрипта.

ЗначениеЧто означает
activeХендшейк был меньше 3 минут назад.
recentХендшейк был в пределах суток.
inactiveХендшейка нет или он устарел (в stats).
no_handshakeХендшейка нет или он устарел (в list).
key_errorКлюча клиента нет в конфигурации сервера.
no_dataДанных недостаточно, чтобы судить.

awgram, сторонний телеграм-бот на Rust, ходит ровно через этот интерфейс: заводит и удаляет клиентов, читает статистику, делает бэкапы. Полное описание контракта - в ADVANCED.md.

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

Нужна ли веб-панель, чтобы управлять клиентами AmneziaWG?
Нет. Вместе с установщиком ставится manage_amneziawg.sh: он добавляет, удаляет, перевыпускает и перечисляет клиентов одной командой по SSH, а для скриптов и ботов отдаёт машиночитаемый JSON. Панель оправдана, только если вы постоянно заводите и меняете клиентов; для сервера, который настроили один раз и забыли, это ещё одна деталь, которую придётся обновлять.
Как добавить клиента на сервер AmneziaWG?
sudo bash /root/awg/manage_amneziawg.sh add phone. Скрипт сам сгенерирует ключи, запишет конфиг, нарисует QR-код и vpn://-ссылку для импорта в приложение Amnezia одним касанием и применит изменение на работающем интерфейсе. Имён можно передать несколько сразу: add phone laptop tablet.
Как удалить клиента и отозвать доступ?
sudo bash /root/awg/manage_amneziawg.sh remove phone. Ключ клиента убирается из конфигурации сервера, изменение применяется на работающем интерфейсе, поэтому старый конфиг перестаёт подключаться сразу и перевыпускать ничего не нужно. Имён тоже можно передать несколько: remove phone laptop.
Можно ли выдать доступ на время?
Да. add guest --expires=7d создаёт клиента, который перестанет работать через указанный срок. Срок пишется как Nh, Nd или Nw: 12h, 7d, 4w. Просроченных снимает cron, проверка идёт каждые пять минут.
Можно ли управлять сервером из скрипта или бота?
Да, через --json. Команды управления отвечают ровно одним JSON-документом на stdout, в том числе когда падают, а человеческие сообщения уходят в stderr. list и stats вместо объекта отдают массив, а show и diagnose флага не понимают. На этом интерфейсе уже работает сторонний телеграм-бот awgram.
Что вернёт команда, если она завершилась ошибкой?
Зависит от того, как именно она упала. Аварийный выход (падение, неверная опция, отказ от подтверждения) даёт ok:false, человекочитаемый error и rc. А пакетная команда вроде add вместо этого расписывает исход по каждому имени внутри results[] и ставит ok:false, поля rc там нет. Источник истины - код возврата процесса, ok его дублирует. Текст ошибки не парсить: решения принимать по ok, rc и status.
Сервер обновил ядро, и туннель перестал работать. Что делать?
repair-module пересобирает модуль ядра через DKMS, загружает его и заново поднимает сервис. Обновление ядра не означает переустановку.