feat: ssh auth, protocol management, and cleanup

This commit is contained in:
infosave2007
2026-01-23 17:55:40 +03:00
parent 4995147bad
commit ea82b78a7d
70 changed files with 16225 additions and 986 deletions
+788
View File
@@ -0,0 +1,788 @@
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en','servers','backup_upload_type','Backup type'),
('en','servers','backup_type_auto','Auto detect'),
('en','servers','backup_type_amnezia','Amnezia app (.backup)'),
('en','servers','backup_type_panel','Panel export (.json)'),
('en','servers','backup_upload_hint','Upload a .backup or .json file. After upload, pick a server entry above.'),
('ru','servers','backup_upload_type','Тип бэкапа'),
('ru','servers','backup_type_auto','Определить автоматически'),
('ru','servers','backup_type_amnezia','Приложение Amnezia (.backup)'),
('ru','servers','backup_type_panel','Экспорт панели (.json)'),
('ru','servers','backup_upload_hint','Загрузите файл .backup или .json. После загрузки выберите сервер выше.'),
('es','servers','backup_upload_type','Tipo de copia de seguridad'),
('es','servers','backup_type_auto','Detectar automáticamente'),
('es','servers','backup_type_amnezia','Aplicación Amnezia (.backup)'),
('es','servers','backup_type_panel','Exportación del panel (.json)'),
('es','servers','backup_upload_hint','Suba un archivo .backup o .json. Después seleccione el servidor arriba.'),
('de','servers','backup_upload_type','Backup-Typ'),
('de','servers','backup_type_auto','Automatisch erkennen'),
('de','servers','backup_type_amnezia','Amnezia-App (.backup)'),
('de','servers','backup_type_panel','Panel-Export (.json)'),
('de','servers','backup_upload_hint','Laden Sie eine .backup- oder .json-Datei hoch. Wählen Sie anschließend oben einen Server aus.'),
('fr','servers','backup_upload_type','Type de sauvegarde'),
('fr','servers','backup_type_auto','Détection automatique'),
('fr','servers','backup_type_amnezia','Application Amnezia (.backup)'),
('fr','servers','backup_type_panel','Export du panneau (.json)'),
('fr','servers','backup_upload_hint','Téléversez un fichier .backup ou .json, puis sélectionnez un serveur ci-dessus.'),
('zh','servers','backup_upload_type','备份类型'),
('zh','servers','backup_type_auto','自动检测'),
('zh','servers','backup_type_amnezia','Amnezia 应用 (.backup)'),
('zh','servers','backup_type_panel','面板导出 (.json)'),
('zh','servers','backup_upload_hint','上传 .backup 或 .json 文件,随后在上方选择服务器。')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en', 'servers', 'config_import_title', 'Import configuration'),
('en', 'servers', 'config_import_hint', 'Upload a configuration backup to update this server and its clients.'),
('en', 'servers', 'config_import_type_label', 'Backup type'),
('en', 'servers', 'config_import_type_panel', 'Panel backup (.json)'),
('en', 'servers', 'config_import_type_amnezia', 'Amnezia app backup (.backup)'),
('en', 'servers', 'config_import_file_label', 'Configuration file'),
('en', 'servers', 'config_import_file_hint', 'Our panel uses .json files. The Amnezia app uses .backup files.'),
('en', 'servers', 'config_import_submit', 'Import configuration'),
('ru', 'servers', 'config_import_title', 'Импорт конфигурации'),
('ru', 'servers', 'config_import_hint', 'Загрузите файл бэкапа, чтобы обновить настройки сервера и список клиентов.'),
('ru', 'servers', 'config_import_type_label', 'Источник бэкапа'),
('ru', 'servers', 'config_import_type_panel', 'Бэкап панели (.json)'),
('ru', 'servers', 'config_import_type_amnezia', 'Бэкап приложения Amnezia (.backup)'),
('ru', 'servers', 'config_import_file_label', 'Файл конфигурации'),
('ru', 'servers', 'config_import_file_hint', 'Панель использует файлы .json. Приложение Amnezia — файлы .backup.'),
('ru', 'servers', 'config_import_submit', 'Импортировать конфигурацию'),
('es', 'servers', 'config_import_title', 'Importar configuración'),
('es', 'servers', 'config_import_hint', 'Cargue un respaldo para actualizar este servidor y sus clientes.'),
('es', 'servers', 'config_import_type_label', 'Tipo de backup'),
('es', 'servers', 'config_import_type_panel', 'Backup del panel (.json)'),
('es', 'servers', 'config_import_type_amnezia', 'Backup de la app Amnezia (.backup)'),
('es', 'servers', 'config_import_file_label', 'Archivo de configuración'),
('es', 'servers', 'config_import_file_hint', 'El panel usa archivos .json. La app Amnezia usa archivos .backup.'),
('es', 'servers', 'config_import_submit', 'Importar configuración'),
('de', 'servers', 'config_import_title', 'Konfiguration importieren'),
('de', 'servers', 'config_import_hint', 'Laden Sie eine Sicherung hoch, um diesen Server und seine Clients zu aktualisieren.'),
('de', 'servers', 'config_import_type_label', 'Backup-Typ'),
('de', 'servers', 'config_import_type_panel', 'Panel-Backup (.json)'),
('de', 'servers', 'config_import_type_amnezia', 'Amnezia-App-Backup (.backup)'),
('de', 'servers', 'config_import_file_label', 'Konfigurationsfile'),
('de', 'servers', 'config_import_file_hint', 'Die Panel-Backups sind .json. Die Amnezia-App nutzt .backup-Dateien.'),
('de', 'servers', 'config_import_submit', 'Konfiguration importieren'),
('fr', 'servers', 'config_import_title', 'Importer la configuration'),
('fr', 'servers', 'config_import_hint', 'Téléversez un fichier de sauvegarde pour mettre à jour ce serveur et ses clients.'),
('fr', 'servers', 'config_import_type_label', 'Type de sauvegarde'),
('fr', 'servers', 'config_import_type_panel', 'Sauvegarde du panneau (.json)'),
('fr', 'servers', 'config_import_type_amnezia', 'Sauvegarde de lapplication Amnezia (.backup)'),
('fr', 'servers', 'config_import_file_label', 'Fichier de configuration'),
('fr', 'servers', 'config_import_file_hint', 'Notre panneau utilise des fichiers .json. Lapplication Amnezia utilise des fichiers .backup.'),
('fr', 'servers', 'config_import_submit', 'Importer la configuration'),
('zh', 'servers', 'config_import_title', '导入配置'),
('zh', 'servers', 'config_import_hint', '上传备份文件以更新此服务器及其客户端。'),
('zh', 'servers', 'config_import_type_label', '备份类型'),
('zh', 'servers', 'config_import_type_panel', '面板备份 (.json)'),
('zh', 'servers', 'config_import_type_amnezia', 'Amnezia 应用备份 (.backup)'),
('zh', 'servers', 'config_import_file_label', '配置文件'),
('zh', 'servers', 'config_import_file_hint', '面板使用 .json 文件,Amnezia 应用使用 .backup 文件。'),
('zh', 'servers', 'config_import_submit', '导入配置')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en','servers','creation_mode','Creation mode'),
('en','servers','creation_mode_manual','Manual setup'),
('en','servers','creation_mode_backup','Import from backup'),
('en','servers','upload_backup_file','Upload backup file'),
('en','servers','backup_upload_hint','Supported formats: panel JSON export or Amnezia application .backup'),
('en','servers','backup_server_entry','Select server entry'),
('en','servers','backup_summary_host','Host'),
('en','servers','backup_summary_clients','Clients'),
('en','servers','config_import_title','Restore configuration from backup'),
('en','servers','config_import_hint','Import server configuration (and optional clients) from a panel export or Amnezia application backup.'),
('en','servers','config_import_type_label','Backup type'),
('en','servers','config_import_type_panel','Panel export (.json)'),
('en','servers','config_import_type_amnezia','Amnezia app backup (.backup)'),
('en','servers','config_import_file_label','Configuration file'),
('en','servers','config_import_file_hint','The file remains on the server only during import and is deleted afterwards.'),
('en','servers','config_import_submit','Import configuration'),
('ru','servers','creation_mode','Режим создания'),
('ru','servers','creation_mode_manual','Ручная настройка'),
('ru','servers','creation_mode_backup','Импорт из бэкапа'),
('ru','servers','upload_backup_file','Загрузите файл бэкапа'),
('ru','servers','backup_upload_hint','Поддерживаются форматы: экспорт панели JSON или бэкап приложения Amnezia (.backup)'),
('ru','servers','backup_server_entry','Выберите запись сервера'),
('ru','servers','backup_summary_host','Хост'),
('ru','servers','backup_summary_clients','Клиенты'),
('ru','servers','config_import_title','Восстановление конфигурации из бэкапа'),
('ru','servers','config_import_hint','Импортируйте конфигурацию сервера (и при необходимости клиентов) из экспорта панели или бэкапа приложения Amnezia.'),
('ru','servers','config_import_type_label','Тип бэкапа'),
('ru','servers','config_import_type_panel','Экспорт панели (.json)'),
('ru','servers','config_import_type_amnezia','Бэкап приложения Amnezia (.backup)'),
('ru','servers','config_import_file_label','Файл конфигурации'),
('ru','servers','config_import_file_hint','Файл хранится на сервере только во время импорта и удаляется сразу после завершения.'),
('ru','servers','config_import_submit','Импортировать конфигурацию')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
CREATE TABLE IF NOT EXISTS protocols (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
slug VARCHAR(100) UNIQUE NOT NULL,
description TEXT,
install_script TEXT,
output_template TEXT,
ubuntu_compatible BOOLEAN DEFAULT false,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_protocols_slug (slug),
INDEX idx_protocols_active (is_active),
INDEX idx_protocols_ubuntu_compatible (ubuntu_compatible)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS protocol_templates (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
protocol_id INT UNSIGNED NOT NULL,
template_name VARCHAR(255) NOT NULL,
template_content TEXT NOT NULL,
is_default BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_protocol_templates_protocol (protocol_id),
INDEX idx_protocol_templates_default (is_default),
FOREIGN KEY (protocol_id) REFERENCES protocols(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS protocol_variables (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
protocol_id INT UNSIGNED NOT NULL,
variable_name VARCHAR(100) NOT NULL,
variable_type VARCHAR(50) NOT NULL DEFAULT 'string',
default_value TEXT,
description TEXT,
required BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_protocol_variables_protocol (protocol_id),
INDEX idx_protocol_variables_name (variable_name),
FOREIGN KEY (protocol_id) REFERENCES protocols(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS server_protocols (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
server_id INT UNSIGNED NOT NULL,
protocol_id INT UNSIGNED NOT NULL,
config_data JSON,
applied_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_server_protocols_server (server_id),
INDEX idx_server_protocols_protocol (protocol_id),
INDEX idx_server_protocols_applied (applied_at),
UNIQUE KEY unique_server_protocol (server_id, protocol_id),
FOREIGN KEY (server_id) REFERENCES vpn_servers(id) ON DELETE CASCADE,
FOREIGN KEY (protocol_id) REFERENCES protocols(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS ai_generations (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
protocol_id INT UNSIGNED NULL,
model_used VARCHAR(100) NOT NULL,
prompt TEXT NOT NULL,
generated_script TEXT,
suggestions JSON,
ubuntu_compatible BOOLEAN,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_ai_generations_protocol (protocol_id),
INDEX idx_ai_generations_model (model_used),
INDEX idx_ai_generations_created (created_at DESC),
FOREIGN KEY (protocol_id) REFERENCES protocols(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO protocols (name, slug, description, install_script, output_template, ubuntu_compatible, is_active)
SELECT 'AmneziaWG Advanced', 'amnezia-wg-advanced', 'AmneziaWG protocol with advanced junk packet obfuscation parameters', '#!/bin/bash
echo "AmneziaWG Advanced installed"
', '[Interface]
PrivateKey = {{private_key}}
Address = {{client_ip}}/32
DNS = 8.8.8.8, 8.8.4.4
[Peer]
PublicKey = {{server_public_key}}
PresharedKey = {{preshared_key}}
Endpoint = {{server_host}}:{{server_port}}
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Jc = {{jc}}
Jmin = {{jmin}}
Jmax = {{jmax}}
S1 = {{s1}}
S2 = {{s2}}
H1 = {{h1}}
H2 = {{h2}}
H3 = {{h3}}
H4 = {{h4}}', true, true
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug='amnezia-wg-advanced');
INSERT INTO protocols (name, slug, description, install_script, output_template, ubuntu_compatible, is_active)
SELECT 'WireGuard Standard', 'wireguard-standard', 'Standard WireGuard VPN protocol', '#!/bin/bash
CONTAINER_NAME="wireguard"
VPN_SUBNET="10.8.2.0/24"
PRIVATE_KEY=$(wg genkey)
PUBLIC_KEY=$(echo $PRIVATE_KEY | wg pubkey)
PRESHARED_KEY=$(wg genpsk)
docker run -d \
--name $CONTAINER_NAME \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-v /opt/wireguard:/etc/wireguard \
linuxserver/wireguard
cat > /opt/wireguard/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.2.1/24
ListenPort = 51820
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.2.2/32
EOF
echo "WireGuard Standard installed successfully"
echo "Server Public Key: $PUBLIC_KEY"', '[Interface]
PrivateKey = {{private_key}}
Address = {{client_ip}}/32
DNS = 8.8.8.8, 8.8.4.4
[Peer]
PublicKey = {{server_public_key}}
PresharedKey = {{preshared_key}}
Endpoint = {{server_host}}:{{server_port}}
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25', true, true
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug='wireguard-standard');
INSERT INTO protocols (name, slug, description, install_script, output_template, ubuntu_compatible, is_active)
SELECT 'OpenVPN', 'openvpn', 'OpenVPN protocol with TCP/UDP support', '#!/bin/bash
CONTAINER_NAME="openvpn"
VPN_SUBNET="10.8.3.0/24"
docker run -d \
--name $CONTAINER_NAME \
--cap-add=NET_ADMIN \
-p 1194:1194/udp \
-p 1194:1194/tcp \
-v /opt/openvpn:/etc/openvpn \
kylemanna/openvpn
docker exec -it $CONTAINER_NAME ovpn_genconfig -u udp://{{server_host}}:1194
docker exec -it $CONTAINER_NAME ovpn_initpki
echo "OpenVPN installed successfully"
echo "Available on ports: 1194/udp, 1194/tcp"', 'client
dev tun
proto {{protocol}}
remote {{server_host}} {{server_port}}
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
verb 3', true, true
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug='openvpn');
INSERT INTO protocols (name, slug, description, install_script, output_template, ubuntu_compatible, is_active)
SELECT 'Shadowsocks', 'shadowsocks', 'Shadowsocks proxy protocol', '#!/bin/bash
CONTAINER_NAME="shadowsocks"
PASSWORD=$(openssl rand -base64 12)
docker run -d \
--name $CONTAINER_NAME \
-p 8388:8388 \
-e METHOD=aes-256-gcm \
-e PASSWORD=$PASSWORD \
shadowsocks/shadowsocks-libev
echo "Shadowsocks installed successfully"
echo "Port: 8388"
echo "Method: aes-256-gcm"
echo "Password: $PASSWORD"', '{
"server": "{{server_host}}",
"server_port": {{server_port}},
"password": "{{password}}",
"method": "{{method}}"
}', true, true
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug='shadowsocks');
INSERT INTO protocol_templates (protocol_id, template_name, template_content, is_default)
SELECT p.id, 'Default AmneziaWG', '[Interface]
PrivateKey = {{private_key}}
Address = {{client_ip}}/32
DNS = 8.8.8.8, 8.8.4.4
[Peer]
PublicKey = {{server_public_key}}
PresharedKey = {{preshared_key}}
Endpoint = {{server_host}}:{{server_port}}
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Jc = {{jc}}
Jmin = {{jmin}}
Jmax = {{jmax}}
S1 = {{s1}}
S2 = {{s2}}
H1 = {{h1}}
H2 = {{h2}}
H3 = {{h3}}
H4 = {{h4}}', true
FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_templates WHERE protocol_id=p.id AND template_name='Default AmneziaWG');
INSERT INTO protocol_templates (protocol_id, template_name, template_content, is_default)
SELECT p.id, 'Default WireGuard', '[Interface]
PrivateKey = {{private_key}}
Address = {{client_ip}}/32
DNS = 8.8.8.8, 8.8.4.4
[Peer]
PublicKey = {{server_public_key}}
PresharedKey = {{preshared_key}}
Endpoint = {{server_host}}:{{server_port}}
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25', true
FROM protocols p WHERE p.slug='wireguard-standard' AND NOT EXISTS (SELECT 1 FROM protocol_templates WHERE protocol_id=p.id AND template_name='Default WireGuard');
INSERT INTO protocol_templates (protocol_id, template_name, template_content, is_default)
SELECT p.id, 'Default OpenVPN', 'client
dev tun
proto {{protocol}}
remote {{server_host}} {{server_port}}
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
verb 3', true
FROM protocols p WHERE p.slug='openvpn' AND NOT EXISTS (SELECT 1 FROM protocol_templates WHERE protocol_id=p.id AND template_name='Default OpenVPN');
INSERT INTO protocol_templates (protocol_id, template_name, template_content, is_default)
SELECT p.id, 'Default Shadowsocks', '{
"server": "{{server_host}}",
"server_port": {{server_port}},
"password": "{{password}}",
"method": "{{method}}"
}', true
FROM protocols p WHERE p.slug='shadowsocks' AND NOT EXISTS (SELECT 1 FROM protocol_templates WHERE protocol_id=p.id AND template_name='Default Shadowsocks');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'private_key', 'string', '', 'Client private key', true FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='private_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'client_ip', 'string', '10.8.1.2', 'Client IP address', true FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='client_ip');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_public_key', 'string', '', 'Server public key', true FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_public_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'preshared_key', 'string', '', 'Pre-shared key for additional security', true FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='preshared_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_host', 'string', '', 'Server hostname or IP', true FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_port', 'number', '51820', 'Server port', true FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_port');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'jc', 'number', '4', 'Junk packet count', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='jc');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'jmin', 'number', '50', 'Minimum junk packet size', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='jmin');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'jmax', 'number', '1000', 'Maximum junk packet size', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='jmax');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 's1', 'number', '148', 'Junk packet size 1', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='s1');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 's2', 'number', '450', 'Junk packet size 2', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='s2');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'h1', 'number', '320121696', 'Junk packet header 1', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='h1');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'h2', 'number', '51525354', 'Junk packet header 2', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='h2');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'h3', 'number', '13141516', 'Junk packet header 3', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='h3');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'h4', 'number', '92435495', 'Junk packet header 4', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='h4');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'private_key', 'string', '', 'Client private key', true FROM protocols p WHERE p.slug='wireguard-standard' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='private_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'client_ip', 'string', '10.8.2.2', 'Client IP address', true FROM protocols p WHERE p.slug='wireguard-standard' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='client_ip');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_public_key', 'string', '', 'Server public key', true FROM protocols p WHERE p.slug='wireguard-standard' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_public_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'preshared_key', 'string', '', 'Pre-shared key for additional security', true FROM protocols p WHERE p.slug='wireguard-standard' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='preshared_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_host', 'string', '', 'Server hostname or IP', true FROM protocols p WHERE p.slug='wireguard-standard' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_port', 'number', '51820', 'Server port', true FROM protocols p WHERE p.slug='wireguard-standard' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_port');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'protocol', 'string', 'udp', 'Connection protocol (udp/tcp)', true FROM protocols p WHERE p.slug='openvpn' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='protocol');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_host', 'string', '', 'Server hostname or IP', true FROM protocols p WHERE p.slug='openvpn' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_port', 'number', '1194', 'Server port', true FROM protocols p WHERE p.slug='openvpn' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_port');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_host', 'string', '', 'Server hostname or IP', true FROM protocols p WHERE p.slug='shadowsocks' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_port', 'number', '8388', 'Server port', true FROM protocols p WHERE p.slug='shadowsocks' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='server_port');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'password', 'string', '', 'Connection password', true FROM protocols p WHERE p.slug='shadowsocks' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='password');
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en','common','cancel','Cancel'),
('ru','common','cancel','Отмена'),
('es','common','cancel','Cancelar'),
('de','common','cancel','Abbrechen'),
('fr','common','cancel','Annuler'),
('zh','common','cancel','取消'),
('en','common','format','Format'),
('ru','common','format','Форматировать'),
('es','common','format','Formatear'),
('de','common','format','Formatieren'),
('fr','common','format','Formater'),
('zh','common','format','格式化'),
('en','common','clear','Clear'),
('ru','common','clear','Очистить'),
('es','common','clear','Borrar'),
('de','common','clear','Leeren'),
('fr','common','clear','Effacer'),
('zh','common','clear','清空'),
('en','protocols','template_editor_help','Use placeholders like {{variable}} and preview client output'),
('ru','protocols','template_editor_help','Используйте плейсхолдеры вида {{variable}} и просматривайте вывод клиента'),
('es','protocols','template_editor_help','Usa marcadores como {{variable}} y previsualiza la salida del cliente'),
('de','protocols','template_editor_help','Verwenden Sie Platzhalter wie {{variable}} und sehen Sie die ClientAusgabe in der Vorschau'),
('fr','protocols','template_editor_help','Utilisez des placeholders comme {{variable}} et prévisualisez la sortie client'),
('zh','protocols','template_editor_help','使用如 {{variable}} 的占位符并预览客户端输出'),
('en','protocols','variable_private_key_help','Client private key'),
('ru','protocols','variable_private_key_help','Приватный ключ клиента'),
('es','protocols','variable_private_key_help','Clave privada del cliente'),
('de','protocols','variable_private_key_help','Privater Schlüssel des Clients'),
('fr','protocols','variable_private_key_help','Clé privée du client'),
('zh','protocols','variable_private_key_help','客户端私钥'),
('en','protocols','variable_public_key_help','Server public key'),
('ru','protocols','variable_public_key_help','Публичный ключ сервера'),
('es','protocols','variable_public_key_help','Clave pública del servidor'),
('de','protocols','variable_public_key_help','Öffentlicher Schlüssel des Servers'),
('fr','protocols','variable_public_key_help','Clé publique du serveur'),
('zh','protocols','variable_public_key_help','服务器公钥'),
('en','protocols','variable_client_ip_help','Client IP address'),
('ru','protocols','variable_client_ip_help','IP‑адрес клиента'),
('es','protocols','variable_client_ip_help','Dirección IP del cliente'),
('de','protocols','variable_client_ip_help','IPAdresse des Clients'),
('fr','protocols','variable_client_ip_help','Adresse IP du client'),
('zh','protocols','variable_client_ip_help','客户端 IP 地址'),
('en','protocols','variable_server_host_help','VPN server host'),
('ru','protocols','variable_server_host_help','Хост VPN‑сервера'),
('es','protocols','variable_server_host_help','Host del servidor VPN'),
('de','protocols','variable_server_host_help','VPNServerHost'),
('fr','protocols','variable_server_host_help','Hôte du serveur VPN'),
('zh','protocols','variable_server_host_help','VPN 服务器主机'),
('en','protocols','variable_server_port_help','VPN server port'),
('ru','protocols','variable_server_port_help','Порт VPN‑сервера'),
('es','protocols','variable_server_port_help','Puerto del servidor VPN'),
('de','protocols','variable_server_port_help','VPNServerPort'),
('fr','protocols','variable_server_port_help','Port du serveur VPN'),
('zh','protocols','variable_server_port_help','VPN 服务器端口'),
('en','protocols','variable_preshared_key_help','WireGuard preshared key'),
('ru','protocols','variable_preshared_key_help','Предварительно общий ключ WireGuard'),
('es','protocols','variable_preshared_key_help','Clave precompartida de WireGuard'),
('de','protocols','variable_preshared_key_help','WireGuardvorausgeteilter Schlüssel'),
('fr','protocols','variable_preshared_key_help','Clé prépartagée WireGuard'),
('zh','protocols','variable_preshared_key_help','WireGuard 预共享密钥')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en','ai','enter_protocol_id_to_apply','Enter protocol ID to apply'),
('ru','ai','enter_protocol_id_to_apply','Введите ID протокола для применения'),
('es','ai','enter_protocol_id_to_apply','Introduce el ID de protocolo para aplicar'),
('de','ai','enter_protocol_id_to_apply','ProtokollID zum Anwenden eingeben'),
('fr','ai','enter_protocol_id_to_apply','Saisissez lID du protocole à appliquer'),
('zh','ai','enter_protocol_id_to_apply','输入要应用的协议 ID'),
('en','ai','improve_protocol','Improve protocol script for'),
('ru','ai','improve_protocol','Улучшить скрипт протокола для'),
('es','ai','improve_protocol','Mejorar script del protocolo для'),
('de','ai','improve_protocol','Protokollskript verbessern für'),
('fr','ai','improve_protocol','Améliorer le script du protocole pour'),
('zh','ai','improve_protocol','改进协议脚本:'),
('en','protocols','enter_protocol_name','Enter protocol name'),
('ru','protocols','enter_protocol_name','Введите имя протокола'),
('es','protocols','enter_protocol_name','Introduce el nombre del protocolo'),
('de','protocols','enter_protocol_name','Protokollnamen eingeben'),
('fr','protocols','enter_protocol_name','Saisissez le nom du protocole'),
('zh','protocols','enter_protocol_name','输入协议名称'),
('en','protocols','enter_protocol_slug','Enter protocol slug'),
('ru','protocols','enter_protocol_slug','Введите slug протокола'),
('es','protocols','enter_protocol_slug','Introduce el slug del protocolo'),
('de','protocols','enter_protocol_slug','ProtokollSlug eingeben'),
('fr','protocols','enter_protocol_slug','Saisissez le slug du protocole'),
('zh','protocols','enter_protocol_slug','输入协议 slug'),
('en','protocols','protocol_created_successfully','Protocol created successfully'),
('ru','protocols','protocol_created_successfully','Протокол успешно создан'),
('es','protocols','protocol_created_successfully','Protocolo creado correctamente'),
('de','protocols','protocol_created_successfully','Protokoll erfolgreich erstellt'),
('fr','protocols','protocol_created_successfully','Protocole créé avec succès'),
('zh','protocols','protocol_created_successfully','协议创建成功'),
('en','protocols','error_creating_protocol','Error creating protocol'),
('ru','protocols','error_creating_protocol','Ошибка создания протокола'),
('es','protocols','error_creating_protocol','Error al crear el protocolo'),
('de','protocols','error_creating_protocol','Fehler beim Erstellen des Protokolls'),
('fr','protocols','error_creating_protocol','Erreur lors de la création du protocole'),
('zh','protocols','error_creating_protocol','创建协议时出错')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en','settings','protocols','Protocols'),
('ru','settings','protocols','Протоколы'),
('es','settings','protocols','Protocolos'),
('de','settings','protocols','Protokolle'),
('fr','settings','protocols','Protocoles'),
('zh','settings','protocols','协议'),
('en','settings','protocol_management','Protocol Management'),
('ru','settings','protocol_management','Управление протоколами'),
('es','settings','protocol_management','Gestión de protocolos'),
('de','settings','protocol_management','Protokollverwaltung'),
('fr','settings','protocol_management','Gestion des protocoles'),
('zh','settings','protocol_management','协议管理')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en','protocols','test_install','Test install'),
('ru','protocols','test_install','Протестировать установку'),
('es','protocols','test_install','Probar instalación'),
('de','protocols','test_install','Installation testen'),
('fr','protocols','test_install','Tester linstallation'),
('zh','protocols','test_install','测试安装'),
('en','protocols','testing_on_ubuntu22','Testing on Ubuntu 22.04 in isolated Docker'),
('ru','protocols','testing_on_ubuntu22','Тест на Ubuntu 22.04 в изолированном Docker'),
('es','protocols','testing_on_ubuntu22','Prueba en Ubuntu 22.04 en Docker aislado'),
('de','protocols','testing_on_ubuntu22','Test auf Ubuntu 22.04 in isoliertem Docker'),
('fr','protocols','testing_on_ubuntu22','Test sur Ubuntu 22.04 dans Docker isolé'),
('zh','protocols','testing_on_ubuntu22','在隔离的 Docker 中于 Ubuntu 22.04 测试'),
('en','protocols','test_result','Test result'),
('ru','protocols','test_result','Результат теста'),
('es','protocols','test_result','Resultado de la prueba'),
('de','protocols','test_result','Testergebnis'),
('fr','protocols','test_result','Résultat du test'),
('zh','protocols','test_result','测试结果'),
('en','protocols','client_output_preview','Client output preview'),
('ru','protocols','client_output_preview','Предпросмотр ответа клиенту'),
('es','protocols','client_output_preview','Vista previa de salida del cliente'),
('de','protocols','client_output_preview','ClientAusgabevorschau'),
('fr','protocols','client_output_preview','Aperçu de la sortie client'),
('zh','protocols','client_output_preview','客户端输出预览'),
('en','protocols','test_failed','Test failed'),
('ru','protocols','test_failed','Ошибка теста'),
('es','protocols','test_failed','La prueba falló'),
('de','protocols','test_failed','Test fehlgeschlagen'),
('fr','protocols','test_failed','Échec du test'),
('zh','protocols','test_failed','测试失败')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO protocols (name, slug, description, install_script, output_template, ubuntu_compatible, is_active, created_at, updated_at)
SELECT 'SMB Server', 'smb', 'Samba SMB file share inside Docker with random host port', '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="${CONTAINER_NAME:-amnezia-smb}"\nPORT_RANGE_START=${PORT_RANGE_START:-30000}\nPORT_RANGE_END=${PORT_RANGE_END:-65000}\nSMB_PORT=$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))\n\n docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true\nmkdir -p /opt/amnezia/smb/share\n docker run -d \\\n --name "$CONTAINER_NAME" \\\n -p "${SMB_PORT}:445" \\\n -v /opt/amnezia/smb/share:/share \\\n dperson/samba -p -u "amnezia;amnezia" -s "share;/share;yes;no;no;amnezia"\n echo "Port: ${SMB_PORT}"\n echo "Password: amnezia"\n', 'smb://{{server_host}}:{{server_port}}/share\nUsername: amnezia\nPassword: {{password}}', true, true, NOW(), NOW()
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug='smb');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT id, 'server_host', 'string', '127.0.0.1', 'Server hostname or IP', true FROM protocols WHERE slug = 'smb' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = (SELECT id FROM protocols WHERE slug='smb') AND variable_name='server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT id, 'server_port', 'number', '445', 'Server port', true FROM protocols WHERE slug = 'smb' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = (SELECT id FROM protocols WHERE slug='smb') AND variable_name='server_port');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT id, 'password', 'string', '', 'Connection password', true FROM protocols WHERE slug = 'smb' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = (SELECT id FROM protocols WHERE slug='smb') AND variable_name='password');
INSERT INTO protocols (name, slug, description, install_script, output_template, ubuntu_compatible, is_active, created_at, updated_at)
SELECT 'XRay VLESS', 'xray-vless', 'XRay VLESS server inside Docker with generated client UUID', '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="${CONTAINER_NAME:-amnezia-xray}"\nPORT_RANGE_START=${PORT_RANGE_START:-30000}\nPORT_RANGE_END=${PORT_RANGE_END:-65000}\nXRAY_PORT=$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))\nCLIENT_ID=$(cat /proc/sys/kernel/random/uuid)\n docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true\nmkdir -p /opt/amnezia/xray\n cat > /opt/amnezia/xray/config.json << EOF\n{\n "inbounds": [\n {\n "listen": "0.0.0.0",\n "port": 443,\n "protocol": "vless",\n "settings": {\n "clients": [\n { "id": "${CLIENT_ID}" }\n ],\n "decryption": "none"\n },\n "streamSettings": {\n "network": "tcp",\n "security": "none"\n }\n }\n ],\n "outbounds": [\n { "protocol": "freedom" }\n ]\n}\nEOF\n docker run -d \\\n --name "$CONTAINER_NAME" \\\n --restart always \\\n -p "${XRAY_PORT}:443" \\\n -v /opt/amnezia/xray:/etc/xray \\\n teddysun/xray\n echo "Port: ${XRAY_PORT}"\n echo "ClientID: ${CLIENT_ID}"\n', 'vless://{{client_id}}@{{server_host}}:{{server_port}}?security=none&type=tcp', true, true, NOW(), NOW()
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug='xray-vless');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT id, 'server_host', 'string', '127.0.0.1', 'Server hostname or IP', true FROM protocols WHERE slug = 'xray-vless' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = (SELECT id FROM protocols WHERE slug='xray-vless') AND variable_name='server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT id, 'server_port', 'number', '443', 'Server port', true FROM protocols WHERE slug = 'xray-vless' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = (SELECT id FROM protocols WHERE slug='xray-vless') AND variable_name='server_port');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT id, 'client_id', 'string', '', 'VLESS client ID (UUID)', true FROM protocols WHERE slug = 'xray-vless' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = (SELECT id FROM protocols WHERE slug='xray-vless') AND variable_name='client_id');
DELIMITER $$
CREATE PROCEDURE add_protocol_column_and_constraints()
BEGIN
IF (SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='vpn_clients' AND COLUMN_NAME='protocol_id') = 0 THEN
ALTER TABLE vpn_clients ADD COLUMN protocol_id INT UNSIGNED NULL AFTER user_id;
END IF;
IF (SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='vpn_clients' AND INDEX_NAME='idx_protocol_id') = 0 THEN
ALTER TABLE vpn_clients ADD INDEX idx_protocol_id (protocol_id);
END IF;
IF (SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='vpn_clients' AND CONSTRAINT_NAME='fk_vpn_clients_protocol') = 0 THEN
ALTER TABLE vpn_clients ADD CONSTRAINT fk_vpn_clients_protocol FOREIGN KEY (protocol_id) REFERENCES protocols(id) ON DELETE SET NULL;
END IF;
END$$
DELIMITER ;
CALL add_protocol_column_and_constraints();
DROP PROCEDURE add_protocol_column_and_constraints;
DELIMITER $$
CREATE PROCEDURE ensure_users_role_column_and_index()
BEGIN
IF (SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='users' AND COLUMN_NAME='role') = 0 THEN
ALTER TABLE users ADD COLUMN role ENUM('admin','user') DEFAULT 'user' AFTER name;
END IF;
IF (SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='users' AND INDEX_NAME='idx_role') = 0 THEN
ALTER TABLE users ADD INDEX idx_role (role);
END IF;
END$$
DELIMITER ;
CALL ensure_users_role_column_and_index();
DROP PROCEDURE ensure_users_role_column_and_index;
DELIMITER $$
CREATE PROCEDURE add_protocols_optional_columns()
BEGIN
IF (SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='protocols' AND COLUMN_NAME='uninstall_script') = 0 THEN
ALTER TABLE protocols ADD COLUMN uninstall_script MEDIUMTEXT NULL AFTER install_script;
END IF;
IF (SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='protocols' AND COLUMN_NAME='password_command') = 0 THEN
ALTER TABLE protocols ADD COLUMN password_command TEXT NULL AFTER uninstall_script;
END IF;
END$$
DELIMITER ;
CALL add_protocols_optional_columns();
DROP PROCEDURE add_protocols_optional_columns;
DELIMITER $$
CREATE PROCEDURE ensure_users_display_name_column()
BEGIN
IF (SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='users' AND COLUMN_NAME='display_name') = 0 THEN
ALTER TABLE users ADD COLUMN display_name VARCHAR(255) NULL AFTER name;
END IF;
END$$
DELIMITER ;
CALL ensure_users_display_name_column();
DROP PROCEDURE ensure_users_display_name_column;
UPDATE users SET display_name = name WHERE (display_name IS NULL OR display_name = '') AND name IS NOT NULL;
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
EXISTING=$(docker ps -aq -f "name=$CONTAINER_NAME" 2>/dev/null | head -1)
if [ -z "$EXISTING" ]; then
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules amneziavpn/amnezia-wg:latest
sleep 2
else
STATUS=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "")
if [ "$STATUS" != "running" ]; then
docker start "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
fi
docker exec -i "$CONTAINER_NAME" sh -lc "mkdir -p /opt/amnezia/awg"
HAS_CONF=$(docker exec "$CONTAINER_NAME" sh -lc "[ -f /opt/amnezia/awg/wg0.conf ] && echo yes || echo no")
if [ "$HAS_CONF" = "yes" ]; then
PORT=$(docker exec "$CONTAINER_NAME" sh -lc "grep -E \"^ListenPort\" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d \"[:space:]\"")
PSK=$(docker exec "$CONTAINER_NAME" cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(docker exec "$CONTAINER_NAME" sh -lc "grep -E \"^PresharedKey\" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d \"[:space:]\"")
fi
PUBKEY=$(docker exec "$CONTAINER_NAME" cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(docker exec "$CONTAINER_NAME" cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
cat > /opt/amnezia/awg/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
S3 = 20
S4 = 10
H1 = 0xDEADBEEF
H2 = 0xCAFEBABE
H3 = 0x12345678
H4 = 0x9ABCDEF0
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
EOF
docker exec "$CONTAINER_NAME" sh -lc "echo $PRIVATE_KEY > /opt/amnezia/awg/wireguard_server_private_key.key"
docker exec "$CONTAINER_NAME" sh -lc "echo $PUBLIC_KEY > /opt/amnezia/awg/wireguard_server_public_key.key"
docker exec "$CONTAINER_NAME" sh -lc "echo $PRESHARED_KEY > /opt/amnezia/awg/wireguard_psk.key"
docker exec "$CONTAINER_NAME" sh -lc "echo [] > /opt/amnezia/awg/clientsTable"
docker exec "$CONTAINER_NAME" wg-quick up /opt/amnezia/awg/wg0.conf || true
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY'
WHERE slug = 'amnezia-wg-advanced';
UPDATE protocols SET
uninstall_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm -fv "$CONTAINER_NAME" 2>/dev/null || true
docker image rm amneziavpn/amnezia-wg:latest 2>/dev/null || true
docker network rm amnezia-dns-net 2>/dev/null || true
rm -rf /opt/amnezia/amnezia-awg 2>/dev/null || true
rm -rf /opt/amnezia/awg 2>/dev/null || true
echo "{\"success\":true,\"message\":\"AmneziaWG uninstalled\"}"'
WHERE slug = 'amnezia-wg-advanced';
DELIMITER $$
CREATE PROCEDURE ensure_vpn_servers_install_columns()
BEGIN
IF (SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='vpn_servers' AND COLUMN_NAME='install_protocol') = 0 THEN
ALTER TABLE vpn_servers ADD COLUMN install_protocol VARCHAR(100) NULL AFTER container_name;
END IF;
IF (SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME='vpn_servers' AND COLUMN_NAME='install_options') = 0 THEN
ALTER TABLE vpn_servers ADD COLUMN install_options JSON NULL AFTER install_protocol;
END IF;
END$$
DELIMITER ;
CALL ensure_vpn_servers_install_columns();
DROP PROCEDURE ensure_vpn_servers_install_columns;
+108
View File
@@ -0,0 +1,108 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
EXISTING=$(docker ps -aq -f "name=$CONTAINER_NAME" 2>/dev/null | head -1)
if [ -z "$EXISTING" ]; then
# Run container with volume mount and keepalive command
# Waits for config file to appear before starting WireGuard
docker run -d --name "$CONTAINER_NAME" \
--restart always \
--privileged \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-p "${VPN_PORT}:${VPN_PORT}/udp" \
-v /lib/modules:/lib/modules \
-v /opt/amnezia/awg:/opt/amnezia/awg \
amneziavpn/amnezia-wg:latest \
sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
else
STATUS=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "")
if [ "$STATUS" != "running" ]; then
docker start "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
fi
# Check for existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
# Extract existing configuration
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Generate keys using the container
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Write config to HOST file (mounted to container)
cat > /opt/amnezia/awg/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
S3 = 20
S4 = 10
H1 = 0xDEADBEEF
H2 = 0xCAFEBABE
H3 = 0x12345678
H4 = 0x9ABCDEF0
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
EOF
# Save keys to files on host
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
# Container is already waiting for config (loop), so it should pick it up automatically.
# But we can also force it if needed, or just wait a moment.
# The loop is: while [ ! -f ... ]; do sleep 1; done; wg-quick up ...
# Since we just wrote the file, the loop will exit and run wg-quick up.
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+220
View File
@@ -0,0 +1,220 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
# Ensure container is running correctly
check_container
STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
elif [ $STATUS -eq 1 ]; then
# If stopped but exists, remove to recreate with correct flags (just in case)
# Or just start it? Better to recreate to ensure volume mounts are correct.
# But if we recreate, we must ensure we mount the volume.
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# If container is missing (or we just removed it), create it
if ! docker ps -q -f name="$CONTAINER_NAME" >/dev/null 2>&1; then
docker run -d --name "$CONTAINER_NAME" \
--restart always \
--privileged \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-p "${VPN_PORT}:${VPN_PORT}/udp" \
-v /lib/modules:/lib/modules \
-v /opt/amnezia/awg:/opt/amnezia/awg \
amneziavpn/amnezia-wg:latest \
sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
# Wait a moment for it to start
sleep 2
fi
# Extract config from HOST file
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# If no host config, check if container exists and try to rescue config
check_container
STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is restarting and no host config found. Attempting to rescue config..."
# Try to copy from container even if restarting (might fail if container is crashing too fast)
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
echo "Rescued config from broken container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
# Now recreate container with rescue config
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
# Re-run script to pick up host config (recursive call or just fall through? Fall through requires logic jump)
# Easier to just exit and let user run again? No, let''s proceed.
# We have config on host now, so the logic below for "new install" needs to be skipped or we need to jump back.
# Let''s just restart the script logic by execing self? No, complex.
# Let''s just set a flag.
HAS_RESCUED=1
else
echo "Could not rescue config. Removing broken container."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
HAS_RESCUED=0
fi
elif [ $STATUS -eq 0 ]; then
# Running. Check if it has config inside but not on host (old version)
if docker exec "$CONTAINER_NAME" [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Container running with internal config. Migrating to host..."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
# Recreate to add volume mount
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
HAS_RESCUED=1
else
# Running but no config? Weird. Treat as fresh.
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
HAS_RESCUED=0
fi
else
HAS_RESCUED=0
fi
# If we rescued config, we need to start the container with mounts
if [ "$HAS_RESCUED" = "1" ]; then
docker run -d --name "$CONTAINER_NAME" \
--restart always \
--privileged \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-p "${VPN_PORT}:${VPN_PORT}/udp" \
-v /lib/modules:/lib/modules \
-v /opt/amnezia/awg:/opt/amnezia/awg \
amneziavpn/amnezia-wg:latest \
sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
# Extract and exit (same logic as top)
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# FRESH INSTALL
docker run -d --name "$CONTAINER_NAME" \
--restart always \
--privileged \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-p "${VPN_PORT}:${VPN_PORT}/udp" \
-v /lib/modules:/lib/modules \
-v /opt/amnezia/awg:/opt/amnezia/awg \
amneziavpn/amnezia-wg:latest \
sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
cat > /opt/amnezia/awg/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
S3 = 20
S4 = 10
H1 = 0xDEADBEEF
H2 = 0xCAFEBABE
H3 = 0x12345678
H4 = 0x9ABCDEF0
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
EOF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+213
View File
@@ -0,0 +1,213 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
# Ensure container is running correctly
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
elif [ $STATUS -eq 1 ]; then
# If stopped but exists, remove to recreate with correct flags
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# If container is missing (or we just removed it), create it
if ! docker ps -q -f name="$CONTAINER_NAME" >/dev/null 2>&1; then
docker run -d --name "$CONTAINER_NAME" \
--restart always \
--privileged \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-p "${VPN_PORT}:${VPN_PORT}/udp" \
-v /lib/modules:/lib/modules \
-v /opt/amnezia/awg:/opt/amnezia/awg \
amneziavpn/amnezia-wg:latest \
sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
# Wait a moment for it to start
sleep 2
fi
# Extract config from HOST file
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# If no host config, check if container exists and try to rescue config
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is restarting and no host config found. Attempting to rescue config..."
# Try to copy from container even if restarting (might fail if container is crashing too fast)
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
echo "Rescued config from broken container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
# Now recreate container with rescue config
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
HAS_RESCUED=1
else
echo "Could not rescue config. Removing broken container."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
HAS_RESCUED=0
fi
elif [ $STATUS -eq 0 ]; then
# Running. Check if it has config inside but not on host (old version)
if docker exec "$CONTAINER_NAME" [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Container running with internal config. Migrating to host..."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
# Recreate to add volume mount
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
HAS_RESCUED=1
else
# Running but no config? Weird. Treat as fresh.
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
HAS_RESCUED=0
fi
else
HAS_RESCUED=0
fi
# If we rescued config, we need to start the container with mounts
if [ "$HAS_RESCUED" = "1" ]; then
docker run -d --name "$CONTAINER_NAME" \
--restart always \
--privileged \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-p "${VPN_PORT}:${VPN_PORT}/udp" \
-v /lib/modules:/lib/modules \
-v /opt/amnezia/awg:/opt/amnezia/awg \
amneziavpn/amnezia-wg:latest \
sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
# Extract and exit (same logic as top)
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# FRESH INSTALL
docker run -d --name "$CONTAINER_NAME" \
--restart always \
--privileged \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
-p "${VPN_PORT}:${VPN_PORT}/udp" \
-v /lib/modules:/lib/modules \
-v /opt/amnezia/awg:/opt/amnezia/awg \
amneziavpn/amnezia-wg:latest \
sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
cat > /opt/amnezia/awg/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
S3 = 20
S4 = 10
H1 = 0xDEADBEEF
H2 = 0xCAFEBABE
H3 = 0x12345678
H4 = 0x9ABCDEF0
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
EOF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+156
View File
@@ -0,0 +1,156 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
elif [ $STATUS -eq 1 ]; then
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
if ! docker ps -q -f name="$CONTAINER_NAME" >/dev/null 2>&1; then
# Run container with volume mount - SINGLE LINE to avoid syntax issues
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
# Stop container to ensure stable copy
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
# SINGLE LINE command
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
cat > /opt/amnezia/awg/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
S3 = 20
S4 = 10
H1 = 0xDEADBEEF
H2 = 0xCAFEBABE
H3 = 0x12345678
H4 = 0x9ABCDEF0
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
EOF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+172
View File
@@ -0,0 +1,172 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Validate existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
if grep -Fq "\$PRIVATE_KEY" /opt/amnezia/awg/wg0.conf; then
echo "Detected broken configuration (unexpanded variables). Removing..."
rm -f /opt/amnezia/awg/wg0.conf
rm -f /opt/amnezia/awg/wireguard_psk.key
rm -f /opt/amnezia/awg/wireguard_server_public_key.key
rm -f /opt/amnezia/awg/wireguard_server_private_key.key
fi
fi
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
elif [ $STATUS -eq 1 ]; then
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
if ! docker ps -q -f name="$CONTAINER_NAME" >/dev/null 2>&1; then
# Run container with volume mount - SINGLE LINE
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
# Validate rescued config
if grep -Fq "\$PRIVATE_KEY" /opt/amnezia/awg/wg0.conf; then
echo "Rescued config is broken. Discarding."
rm -f /opt/amnezia/awg/wg0.conf
else
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Use WG_CONF delimiter to avoid EOF replacement in PHP
cat > /opt/amnezia/awg/wg0.conf << WG_CONF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
S3 = 20
S4 = 10
H1 = 0xDEADBEEF
H2 = 0xCAFEBABE
H3 = 0x12345678
H4 = 0x9ABCDEF0
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
WG_CONF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+177
View File
@@ -0,0 +1,177 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Validate existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
# Check for unexpanded variables
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then
echo "Detected broken configuration (unexpanded variables). Removing..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for invalid parameters S3/S4
if grep -Eiq "^S3\s*=" /opt/amnezia/awg/wg0.conf || grep -Eiq "^S4\s*=" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid parameters (S3/S4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
fi
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
elif [ $STATUS -eq 1 ]; then
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
if ! docker ps -q -f name="$CONTAINER_NAME" >/dev/null 2>&1; then
# Run container with volume mount - SINGLE LINE
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
# Validate rescued config
IS_BROKEN=0
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^S3\s*=" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if [ "$IS_BROKEN" = "1" ]; then
echo "Rescued config is broken. Discarding."
rm -f /opt/amnezia/awg/wg0.conf
else
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Use WG_CONF delimiter to avoid EOF replacement in PHP
cat > /opt/amnezia/awg/wg0.conf << WG_CONF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
H1 = 0xDEADBEEF
H2 = 0xCAFEBABE
H3 = 0x12345678
H4 = 0x9ABCDEF0
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
WG_CONF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+183
View File
@@ -0,0 +1,183 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Validate existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
# Check for unexpanded variables
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then
echo "Detected broken configuration (unexpanded variables). Removing..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for invalid parameters S3/S4
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf || grep -Eiq "^S4[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid parameters (S3/S4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for hex H-params
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid hex parameters (H1-H4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
fi
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
elif [ $STATUS -eq 1 ]; then
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
if ! docker ps -q -f name="$CONTAINER_NAME" >/dev/null 2>&1; then
# Run container with volume mount - SINGLE LINE
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
# Validate rescued config
IS_BROKEN=0
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if [ "$IS_BROKEN" = "1" ]; then
echo "Rescued config is broken. Discarding."
rm -f /opt/amnezia/awg/wg0.conf
else
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Use WG_CONF delimiter to avoid EOF replacement in PHP
cat > /opt/amnezia/awg/wg0.conf << WG_CONF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
H1 = 1
H2 = 2
H3 = 3
H4 = 4
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
WG_CONF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+184
View File
@@ -0,0 +1,184 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Validate existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
# Check for unexpanded variables
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then
echo "Detected broken configuration (unexpanded variables). Removing..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for invalid parameters S3/S4
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf || grep -Eiq "^S4[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid parameters (S3/S4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for hex H-params
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid hex parameters (H1-H4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for empty PublicKey
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then
echo "Detected empty PublicKey. Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
fi
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
elif [ $STATUS -eq 1 ]; then
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
if ! docker ps -q -f name="$CONTAINER_NAME" >/dev/null 2>&1; then
# Run container with volume mount - SINGLE LINE
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
# Validate rescued config
IS_BROKEN=0
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if [ "$IS_BROKEN" = "1" ]; then
echo "Rescued config is broken. Discarding."
rm -f /opt/amnezia/awg/wg0.conf
else
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Use WG_CONF delimiter to avoid EOF replacement in PHP
cat > /opt/amnezia/awg/wg0.conf << WG_CONF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
H1 = 1
H2 = 2
H3 = 3
H4 = 4
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
WG_CONF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+188
View File
@@ -0,0 +1,188 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Validate existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
# Check for unexpanded variables
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then
echo "Detected broken configuration (unexpanded variables). Removing..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for invalid parameters S3/S4
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf || grep -Eiq "^S4[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid parameters (S3/S4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for hex H-params
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid hex parameters (H1-H4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for empty PublicKey
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then
echo "Detected empty PublicKey. Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
fi
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
VPN_PORT=${PORT:-$VPN_PORT}
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
STATUS=1
elif [ $STATUS -eq 0 ]; then
echo "Container is running."
fi
# Ensure container is running
if [ $STATUS -ne 0 ]; then
echo "Starting container..."
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: $VPN_PORT"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey: $PSK"; fi
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
# Validate rescued config
IS_BROKEN=0
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if [ "$IS_BROKEN" = "1" ]; then
echo "Rescued config is broken. Discarding."
rm -f /opt/amnezia/awg/wg0.conf
else
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey: $PSK"; fi
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Use WG_CONF delimiter to avoid EOF replacement in PHP
cat > /opt/amnezia/awg/wg0.conf << WG_CONF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
H1 = 1
H2 = 2
H3 = 3
H4 = 4
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
WG_CONF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey: $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+22
View File
@@ -0,0 +1,22 @@
-- Backfill XRay server_port from extras.result keys produced by set -x
UPDATE server_protocols sp
JOIN protocols p ON p.id = sp.protocol_id
SET sp.config_data = JSON_SET(sp.config_data, '$.server_port', JSON_EXTRACT(sp.config_data, '$.extras.result."+_xray_port"')),
sp.applied_at = NOW()
WHERE p.slug = 'xray-vless'
AND (
JSON_EXTRACT(sp.config_data, '$.server_port') IS NULL OR
JSON_UNQUOTE(JSON_EXTRACT(sp.config_data, '$.server_port')) = ''
)
AND JSON_EXTRACT(sp.config_data, '$.extras.result."+_xray_port"') IS NOT NULL;
UPDATE server_protocols sp
JOIN protocols p ON p.id = sp.protocol_id
SET sp.config_data = JSON_SET(sp.config_data, '$.server_port', JSON_EXTRACT(sp.config_data, '$.extras.result.xray_port')),
sp.applied_at = NOW()
WHERE p.slug = 'xray-vless'
AND (
JSON_EXTRACT(sp.config_data, '$.server_port') IS NULL OR
JSON_UNQUOTE(JSON_EXTRACT(sp.config_data, '$.server_port')) = ''
)
AND JSON_EXTRACT(sp.config_data, '$.extras.result.xray_port') IS NOT NULL;
+18
View File
@@ -0,0 +1,18 @@
-- Update XRay VLESS protocol to Reality/Vision setup
UPDATE protocols SET install_script = '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="${CONTAINER_NAME:-amnezia-xray}"\nPORT_RANGE_START=${PORT_RANGE_START:-30000}\nPORT_RANGE_END=${PORT_RANGE_END:-65000}\nXRAY_PORT=$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))\n\nPRIVATE_KEY=$(docker run --rm teddysun/xray xray x25519 | grep "Private key:" | awk ''{print $3}'')\nPUBLIC_KEY=$(docker run --rm teddysun/xray xray x25519 -i "$PRIVATE_KEY" | grep "Public key:" | awk ''{print $3}'')\nSHORT_ID=$(openssl rand -hex 8)\nCLIENT_ID=$(cat /proc/sys/kernel/random/uuid)\n\nSERVER_NAME="www.googletagmanager.com"\nFINGERPRINT="chrome"\nSPIDER_X="/"\n\ndocker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true\nmkdir -p /opt/amnezia/xray\n\ncat > /opt/amnezia/xray/server.json << EOF\n{\n "log": { "loglevel": "warning" },\n "inbounds": [\n {\n "listen": "0.0.0.0",\n "port": ${XRAY_PORT},\n "protocol": "vless",\n "settings": {\n "clients": [ { "id": "${CLIENT_ID}" } ],\n "decryption": "none",\n "fallbacks": [ { "dest": 80 } ]\n },\n "streamSettings": {\n "network": "tcp",\n "security": "reality",\n "realitySettings": {\n "show": false,\n "dest": "${SERVER_NAME}:443",\n "xver": 0,\n "serverNames": [ "${SERVER_NAME}" ],\n "privateKey": "${PRIVATE_KEY}",\n "shortIds": [ "${SHORT_ID}" ],\n "fingerprint": "${FINGERPRINT}",\n "spiderX": "${SPIDER_X}"\n }\n }\n }\n ],\n "outbounds": [ { "protocol": "freedom", "tag": "direct" } ]\n}\nEOF\n\n# start container\ndocker run -d \\\n --name "$CONTAINER_NAME" \\\n --restart always \\\n -p "${XRAY_PORT}:${XRAY_PORT}" \\\n -v /opt/amnezia/xray:/opt/amnezia/xray \\\n teddysun/xray xray run -c /opt/amnezia/xray/server.json\n\nsleep 2\n\n# panel output\necho "Port: ${XRAY_PORT}"\necho "ClientID: ${CLIENT_ID}"\necho "PublicKey: ${PUBLIC_KEY}"\necho "PrivateKey: ${PRIVATE_KEY}"\necho "ShortID: ${SHORT_ID}"\necho "ServerName: ${SERVER_NAME}"',
output_template = 'vless://{{client_id}}@{{server_host}}:{{server_port}}?encryption=none&flow=xtls-rprx-vision&security=reality&sni={{reality_server_name}}&fp=chrome&pbk={{reality_public_key}}&sid={{reality_short_id}}&type=tcp'
WHERE slug = 'xray-vless';
-- Ensure protocol variables exist
SET @pid = (SELECT id FROM protocols WHERE slug = 'xray-vless');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, description, required)
SELECT @pid, 'reality_public_key', 'string', 'Reality public key (base64url)', true
WHERE NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=@pid AND variable_name='reality_public_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, description, required)
SELECT @pid, 'reality_short_id', 'string', 'Reality shortId', true
WHERE NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=@pid AND variable_name='reality_short_id');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, description, required)
SELECT @pid, 'reality_server_name', 'string', 'SNI server name for Reality', true
WHERE NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=@pid AND variable_name='reality_server_name');
+4
View File
@@ -0,0 +1,4 @@
-- Set uninstall script for XRay VLESS protocol
UPDATE protocols
SET uninstall_script = '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="${SERVER_CONTAINER:-${CONTAINER_NAME:-amnezia-xray}}"\n\ndocker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true\nrm -rf /opt/amnezia/xray || true\n\necho "Uninstalled: ${CONTAINER_NAME}"\n'
WHERE slug = 'xray-vless';
@@ -0,0 +1,4 @@
-- Make XRay Reality install script robust (keys generation and container name)
UPDATE protocols
SET install_script = '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="amnezia-xray"\nPORT_RANGE_START=${PORT_RANGE_START:-30000}\nPORT_RANGE_END=${PORT_RANGE_END:-65000}\nXRAY_PORT=$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))\n\n# ensure image exists to avoid pull logs mixing with key output\ndocker pull teddysun/xray >/dev/null 2>&1 || true\n\nGEN=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 2>/dev/null || true)\nPRIVATE_KEY=$(printf "%s\n" "$GEN" | awk -F": " "/[Pp]rivate/ {print \\$2}" | tr -d " \\t\\r\\n")\nPUBLIC_KEY=$(printf "%s\n" "$GEN" | awk -F": " "/[Pp]ublic/ {print \\$2}" | tr -d " \\t\\r\\n")\n\nif [ -z "$PRIVATE_KEY" ]; then\n PRIVATE_KEY=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 2>/dev/null | awk -F": " "/[Pp]rivate/ {print \\$2}" | tr -d " \\t\\r\\n" || true)\nfi\nif [ -z "$PUBLIC_KEY" ]; then\n PUBLIC_KEY=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 -i "$PRIVATE_KEY" 2>/dev/null | awk -F": " "/[Pp]ublic/ {print \\$2}" | tr -d " \\t\\r\\n" || true)\nfi\n\nSHORT_ID=$(openssl rand -hex 8)\nCLIENT_ID=$(cat /proc/sys/kernel/random/uuid)\n\nSERVER_NAME="${SERVER_NAME:-www.googletagmanager.com}"\nFINGERPRINT="${FINGERPRINT:-chrome}"\nSPIDER_X="${SPIDER_X:-/}"\n\ndocker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true\nmkdir -p /opt/amnezia/xray\n\ncat > /opt/amnezia/xray/server.json << EOF\n{\n "log": { "loglevel": "warning" },\n "inbounds": [\n {\n "listen": "0.0.0.0",\n "port": ${XRAY_PORT},\n "protocol": "vless",\n "settings": {\n "clients": [ { "id": "${CLIENT_ID}" } ],\n "decryption": "none"\n },\n "streamSettings": {\n "network": "tcp",\n "security": "reality",\n "realitySettings": {\n "show": false,\n "dest": "${SERVER_NAME}:443",\n "xver": 0,\n "serverNames": [ "${SERVER_NAME}" ],\n "privateKey": "${PRIVATE_KEY}",\n "shortIds": [ "${SHORT_ID}" ],\n "fingerprint": "${FINGERPRINT}",\n "spiderX": "${SPIDER_X}"\n }\n }\n }\n ],\n "outbounds": [ { "protocol": "freedom", "tag": "direct" } ]\n}\nEOF\n\n# start container\ndocker run -d \\\n --name "$CONTAINER_NAME" \\\n --restart always \\\n -p "${XRAY_PORT}:${XRAY_PORT}" \\\n -v /opt/amnezia/xray:/opt/amnezia/xray \\\n teddysun/xray xray run -c /opt/amnezia/xray/server.json\n\nsleep 2\n\n# panel output\necho "Port: ${XRAY_PORT}"\necho "ClientID: ${CLIENT_ID}"\necho "PublicKey: ${PUBLIC_KEY}"\necho "PrivateKey: ${PRIVATE_KEY}"\necho "ShortID: ${SHORT_ID}"\necho "ServerName: ${SERVER_NAME}"\necho "ContainerName: ${CONTAINER_NAME}"'
WHERE slug = 'xray-vless';
+4
View File
@@ -0,0 +1,4 @@
-- Fix PublicKey extraction and ShortID generation in XRay install script
UPDATE protocols
SET install_script = '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="${CONTAINER_NAME:-amnezia-xray}"\nPORT_RANGE_START=${PORT_RANGE_START:-30000}\nPORT_RANGE_END=${PORT_RANGE_END:-65000}\nXRAY_PORT=$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))\n\n# Ensure image present to avoid noisy pull output\ndocker pull teddysun/xray >/dev/null 2>&1 || true\n\n# Generate keys\nGEN=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 2>/dev/null || true)\nPRIVATE_KEY=$(printf "%s\n" "$GEN" | sed -n -E "s/^[Pp]rivate[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \t\r\n")\nPUBLIC_KEY=$(printf "%s\n" "$GEN" | sed -n -E "s/^[Pp]ublic[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \t\r\n")\n\nif [ -z "$PUBLIC_KEY" ]; then\n PUBLIC_KEY=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 -i "$PRIVATE_KEY" 2>/dev/null | sed -n -E "s/^[Pp]ublic[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \t\r\n" || true)\nfi\n\n# Generate shortId without openssl\nSHORT_ID=$(od -An -tx1 -N8 /dev/urandom | tr -d " \n")\nCLIENT_ID=$(cat /proc/sys/kernel/random/uuid)\n\nSERVER_NAME="${SERVER_NAME:-www.googletagmanager.com}"\nFINGERPRINT="${FINGERPRINT:-chrome}"\nSPIDER_X="${SPIDER_X:-/}"\n\ndocker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true\nmkdir -p /opt/amnezia/xray\n\ncat > /opt/amnezia/xray/server.json << EOF\n{\n "log": { "loglevel": "warning" },\n "inbounds": [\n {\n "listen": "0.0.0.0",\n "port": ${XRAY_PORT},\n "protocol": "vless",\n "settings": {\n "clients": [ { "id": "${CLIENT_ID}" } ],\n "decryption": "none"\n },\n "streamSettings": {\n "network": "tcp",\n "security": "reality",\n "realitySettings": {\n "show": false,\n "dest": "${SERVER_NAME}:443",\n "xver": 0,\n "serverNames": [ "${SERVER_NAME}" ],\n "privateKey": "${PRIVATE_KEY}",\n "shortIds": [ "${SHORT_ID}" ],\n "fingerprint": "${FINGERPRINT}",\n "spiderX": "${SPIDER_X}"\n }\n }\n }\n ],\n "outbounds": [ { "protocol": "freedom", "tag": "direct" } ]\n}\nEOF\n\n# Start container\ndocker run -d \\\n --name "$CONTAINER_NAME" \\\n --restart always \\\n -p "${XRAY_PORT}:${XRAY_PORT}" \\\n -v /opt/amnezia/xray:/opt/amnezia/xray \\\n teddysun/xray xray run -c /opt/amnezia/xray/server.json\n\nsleep 2\n\n# Output configuration\necho "Port: ${XRAY_PORT}"\necho "ClientID: ${CLIENT_ID}"\necho "PublicKey: ${PUBLIC_KEY}"\necho "PrivateKey: ${PRIVATE_KEY}"\necho "ShortID: ${SHORT_ID}"\necho "ServerName: ${SERVER_NAME}"\necho "ContainerName: ${CONTAINER_NAME}"'
WHERE slug = 'xray-vless';
@@ -0,0 +1,3 @@
UPDATE protocols
SET install_script = '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="${CONTAINER_NAME:-amnezia-xray}"\nPORT_RANGE_START=${PORT_RANGE_START:-30000}\nPORT_RANGE_END=${PORT_RANGE_END:-65000}\nXRAY_PORT=${SERVER_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}\n\n# Ensure image present to avoid noisy pull output\ndocker pull teddysun/xray >/dev/null 2>&1 || true\n\n# Generate keys\nGEN=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 2>/dev/null || true)\nPRIVATE_KEY=$(printf "%s\\n" "$GEN" | sed -n -E "s/^[Pp]rivate[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \\t\\r\\n")\nPUBLIC_KEY=$(printf "%s\\n" "$GEN" | sed -n -E "s/^[Pp]ublic[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \\t\\r\\n")\n\nif [ -z "$PUBLIC_KEY" ] && [ -n "$PRIVATE_KEY" ]; then\n PUBLIC_KEY=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 -i "$PRIVATE_KEY" 2>/dev/null | sed -n -E "s/^[Pp]ublic[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \\t\\r\\n" || true)\nfi\n\nSHORT_ID=$(od -An -tx1 -N8 /dev/urandom | tr -d " \\n")\nCLIENT_ID=$(cat /proc/sys/kernel/random/uuid)\n\nSERVER_NAME="${SERVER_NAME:-www.googletagmanager.com}"\nFINGERPRINT="${FINGERPRINT:-chrome}"\nSPIDER_X="${SPIDER_X:-/}"\n\ndocker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true\nmkdir -p /opt/amnezia/xray\n\ncat > /opt/amnezia/xray/server.json << EOF\n{\n "log": { "loglevel": "warning" },\n "inbounds": [\n {\n "listen": "0.0.0.0",\n "port": ${XRAY_PORT},\n "protocol": "vless",\n "settings": {\n "clients": [ { "id": "${CLIENT_ID}" } ],\n "decryption": "none"\n },\n "streamSettings": {\n "network": "tcp",\n "security": "reality",\n "realitySettings": {\n "show": false,\n "dest": "${SERVER_NAME}:443",\n "xver": 0,\n "serverNames": [ "${SERVER_NAME}" ],\n "privateKey": "${PRIVATE_KEY}",\n "shortIds": [ "${SHORT_ID}" ],\n "fingerprint": "${FINGERPRINT}",\n "spiderX": "${SPIDER_X}"\n }\n }\n }\n ],\n "outbounds": [ { "protocol": "freedom", "tag": "direct" } ]\n}\nEOF\n\n# Start container\ndocker run -d \\\n --name "$CONTAINER_NAME" \\\n --restart always \\\n -p "${XRAY_PORT}:${XRAY_PORT}" \\\n -v /opt/amnezia/xray:/opt/amnezia/xray \\\n teddysun/xray xray run -c /opt/amnezia/xray/server.json\n\nsleep 2\n\n# Output configuration\necho "XrayPort: ${XRAY_PORT}"\necho "Port: ${XRAY_PORT}"\necho "ClientID: ${CLIENT_ID}"\necho "PublicKey: ${PUBLIC_KEY}"\necho "PrivateKey: ${PRIVATE_KEY}"\necho "ShortID: ${SHORT_ID}"\necho "ServerName: ${SERVER_NAME}"\necho "ContainerName: ${CONTAINER_NAME}"'
WHERE slug = 'xray-vless';
+3
View File
@@ -0,0 +1,3 @@
UPDATE protocols
SET install_script = '#!/bin/bash\n\nset -euo pipefail\nset -x\n\nCONTAINER_NAME="${CONTAINER_NAME:-amnezia-xray}"\nXRAY_PORT=${SERVER_PORT:-443}\n\n# Ensure image present to avoid noisy pull output\ndocker pull teddysun/xray >/dev/null 2>&1 || true\n\n# Generate keys\nGEN=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 2>/dev/null || true)\nPRIVATE_KEY=$(printf "%s\\n" "$GEN" | sed -n -E "s/^[Pp]rivate[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \\t\\r\\n")\nPUBLIC_KEY=$(printf "%s\\n" "$GEN" | sed -n -E "s/^[Pp]ublic[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \\t\\r\\n")\n\nif [ -z "$PUBLIC_KEY" ] && [ -n "$PRIVATE_KEY" ]; then\n PUBLIC_KEY=$(docker run --rm --entrypoint /usr/bin/xray teddysun/xray x25519 -i "$PRIVATE_KEY" 2>/dev/null | sed -n -E "s/^[Pp]ublic[[:space:]]*[Kk]ey:[[:space:]]*(.*)$/\\1/p" | tr -d " \\t\\r\\n" || true)\nfi\n\nSHORT_ID=$(od -An -tx1 -N8 /dev/urandom | tr -d " \\n")\nCLIENT_ID=$(cat /proc/sys/kernel/random/uuid)\n\nSERVER_NAME="${SERVER_NAME:-www.googletagmanager.com}"\nFINGERPRINT="${FINGERPRINT:-chrome}"\nSPIDER_X="${SPIDER_X:-/}"\n\ndocker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true\nmkdir -p /opt/amnezia/xray\n\ncat > /opt/amnezia/xray/server.json << EOF\n{\n "log": { "loglevel": "warning" },\n "inbounds": [\n {\n "listen": "0.0.0.0",\n "port": ${XRAY_PORT},\n "protocol": "vless",\n "settings": {\n "clients": [ { "id": "${CLIENT_ID}" } ],\n "decryption": "none"\n },\n "streamSettings": {\n "network": "tcp",\n "security": "reality",\n "realitySettings": {\n "show": false,\n "dest": "${SERVER_NAME}:443",\n "xver": 0,\n "serverNames": [ "${SERVER_NAME}" ],\n "privateKey": "${PRIVATE_KEY}",\n "shortIds": [ "${SHORT_ID}" ],\n "fingerprint": "${FINGERPRINT}",\n "spiderX": "${SPIDER_X}"\n }\n }\n }\n ],\n "outbounds": [ { "protocol": "freedom", "tag": "direct" } ]\n}\nEOF\n\n# Start container\ndocker run -d \\\n --name "$CONTAINER_NAME" \\\n --restart always \\\n -p "${XRAY_PORT}:${XRAY_PORT}" \\\n -v /opt/amnezia/xray:/opt/amnezia/xray \\\n teddysun/xray xray run -c /opt/amnezia/xray/server.json\n\nsleep 2\n\n# Output configuration\necho "XrayPort: ${XRAY_PORT}"\necho "Port: ${XRAY_PORT}"\necho "ClientID: ${CLIENT_ID}"\necho "PublicKey: ${PUBLIC_KEY}"\necho "PrivateKey: ${PRIVATE_KEY}"\necho "ShortID: ${SHORT_ID}"\necho "ServerName: ${SERVER_NAME}"\necho "ContainerName: ${CONTAINER_NAME}"'
WHERE slug = 'xray-vless';
+49
View File
@@ -0,0 +1,49 @@
ALTER TABLE protocols ADD COLUMN qr_code_template MEDIUMTEXT DEFAULT NULL;
ALTER TABLE protocols ADD COLUMN qr_code_format VARCHAR(50) DEFAULT 'amnezia_compressed';
-- Update AmneziaWG and WireGuard
UPDATE protocols SET qr_code_template = '{
"containers": [
{
"awg": {
"H1": "{{H1}}",
"H2": "{{H2}}",
"H3": "{{H3}}",
"H4": "{{H4}}",
"Jc": "{{Jc}}",
"Jmax": "{{Jmax}}",
"Jmin": "{{Jmin}}",
"S1": "{{S1}}",
"S2": "{{S2}}",
"last_config": {{last_config_json}},
"port": "{{port}}",
"transport_proto": "udp"
},
"container": "amnezia-awg"
}
],
"defaultContainer": "amnezia-awg",
"description": "{{description}}",
"dns1": "{{dns1}}",
"dns2": "{{dns2}}",
"hostName": "{{hostName}}"
}' WHERE slug IN ('amnezia-wg', 'wireguard', 'amnezia-wg-advanced');
-- Update XRay
UPDATE protocols SET qr_code_template = '{
"containers": [
{
"container": "amnezia-xray",
"xray": {
"last_config": {{last_config_json}},
"port": "{{port}}",
"transport_proto": "tcp"
}
}
],
"defaultContainer": "amnezia-xray",
"description": "{{description}}",
"dns1": "1.1.1.1",
"dns2": "1.0.0.1",
"hostName": "{{hostName}}"
}' WHERE slug LIKE '%xray%';
@@ -0,0 +1,10 @@
-- Add translations for QR code template UI
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en', 'protocols', 'qr_code_template', 'QR Code Template'),
('en', 'protocols', 'qr_code_format', 'QR Code Format'),
('en', 'protocols', 'qr_code_format_help', 'Select the format for the QR code payload. "Amnezia Compressed" uses the legacy Qt/QDataStream format. "Raw Content" uses the template output directly.'),
('en', 'protocols', 'qr_code_template_help', 'Template for the QR code payload. Use {{last_config_json}} to include the full configuration as a JSON object.'),
('en', 'protocols', 'variable_last_config_json_help', 'Full configuration as a JSON object (required for Amnezia format)'),
('en', 'protocols', 'plus_all_output_variables', 'Plus all variables from the Output Template section'),
('en', 'ai', 'prompt_placeholder_qr_template', 'Describe how the QR code payload should be structured (e.g., "Standard WireGuard config format" or "JSON with specific fields")')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
@@ -0,0 +1,70 @@
-- Add Russian translations for Protocol Editor
INSERT INTO translations (locale, category, key_name, translation) VALUES
('ru', 'protocols', 'edit_protocol', 'Редактирование протокола'),
('ru', 'protocols', 'create_protocol', 'Создание протокола'),
('ru', 'protocols', 'edit_protocol_description', 'Изменение настроек и скриптов протокола'),
('ru', 'protocols', 'create_protocol_description', 'Добавление нового протокола в систему'),
('ru', 'protocols', 'back_to_protocols', 'К списку протоколов'),
('ru', 'protocols', 'basic_information', 'Основная информация'),
('ru', 'protocols', 'name_label', 'Название'),
('ru', 'protocols', 'name_help', 'Отображаемое имя протокола'),
('ru', 'protocols', 'slug_label', 'Слаг (ID)'),
('ru', 'protocols', 'slug_help', 'Уникальный идентификатор (латиница, цифры, дефис)'),
('ru', 'protocols', 'description_help', 'Краткое описание протокола'),
('ru', 'protocols', 'installation_script', 'Скрипт установки'),
('ru', 'protocols', 'install_script_help', 'Bash скрипт, который будет выполнен при установке протокола'),
('ru', 'protocols', 'uninstallation_script', 'Скрипт удаления'),
('ru', 'protocols', 'uninstall_script_help', 'Bash скрипт, который будет выполнен при удалении протокола'),
('ru', 'protocols', 'test_install', 'Тест установки'),
('ru', 'protocols', 'test_uninstall', 'Тест удаления'),
('ru', 'protocols', 'testing_on_ubuntu22', 'Тестирование на Ubuntu 22.04 (Docker)'),
('ru', 'protocols', 'test_result', 'Результат выполнения'),
('ru', 'protocols', 'client_output_preview', 'Предпросмотр конфига клиента'),
('ru', 'protocols', 'output_template', 'Шаблон конфигурации'),
('ru', 'protocols', 'output_template_help', 'Шаблон для генерации файла конфигурации клиента. Используйте переменные {{variable}}'),
('ru', 'protocols', 'available_variables', 'Доступные переменные'),
('ru', 'protocols', 'variable_private_key_help', 'Приватный ключ клиента'),
('ru', 'protocols', 'variable_public_key_help', 'Публичный ключ сервера'),
('ru', 'protocols', 'variable_client_ip_help', 'IP-адрес клиента'),
('ru', 'protocols', 'variable_server_host_help', 'Хост сервера (IP или домен)'),
('ru', 'protocols', 'variable_server_port_help', 'Порт сервера'),
('ru', 'protocols', 'variable_preshared_key_help', 'Дополнительный ключ шифрования (PSK)'),
('ru', 'protocols', 'variable_last_config_json_help', 'Полная конфигурация в формате JSON (для Amnezia)'),
('ru', 'protocols', 'plus_all_output_variables', 'Плюс все переменные из шаблона конфигурации'),
('ru', 'protocols', 'qr_code_template', 'Шаблон QR-кода'),
('ru', 'protocols', 'qr_code_template_help', 'Шаблон для формирования содержимого QR-кода'),
('ru', 'protocols', 'qr_code_format', 'Формат QR-кода'),
('ru', 'protocols', 'qr_code_format_help', 'Выберите формат данных в QR-коде'),
('ru', 'protocols', 'password_generation', 'Генерация пароля'),
('ru', 'protocols', 'password_command_help', 'Команда для генерации пароля/ключа (выполняется перед установкой)'),
('ru', 'protocols', 'ubuntu_compatible', 'Совместим с Ubuntu'),
('ru', 'protocols', 'active_label', 'Активен'),
('ru', 'protocols', 'update_protocol', 'Обновить протокол'),
('ru', 'protocols', 'save_protocol', 'Сохранить протокол'),
('ru', 'protocols', 'please_fill_required_fields', 'Пожалуйста, заполните обязательные поля'),
('ru', 'protocols', 'invalid_slug_format', 'Неверный формат слага'),
('ru', 'ai', 'get_ai_help', 'Помощь AI'),
('ru', 'ai', 'assistant', 'AI Ассистент'),
('ru', 'ai', 'select_model', 'Выберите модель'),
('ru', 'ai', 'model_gpt35_turbo', 'GPT-3.5 Turbo'),
('ru', 'ai', 'model_gpt4', 'GPT-4'),
('ru', 'ai', 'model_claude3_haiku', 'Claude 3 Haiku'),
('ru', 'ai', 'model_claude3_sonnet', 'Claude 3 Sonnet'),
('ru', 'ai', 'custom_model_placeholder', 'Или введите имя модели вручную'),
('ru', 'ai', 'check_availability', 'Проверить'),
('ru', 'ai', 'protocol_type', 'Тип протокола'),
('ru', 'ai', 'general_vpn', 'Общий VPN'),
('ru', 'ai', 'describe_requirements', 'Опишите требования'),
('ru', 'ai', 'prompt_placeholder', 'Например: Скрипт для установки Shadowsocks на порт 8388...'),
('ru', 'ai', 'prompt_placeholder_template', 'Например: Конфиг в формате JSON с полями server, port, password...'),
('ru', 'ai', 'prompt_placeholder_qr_template', 'Например: Ссылка вида vless://uuid@host:port...'),
('ru', 'ai', 'prompt_placeholder_uninstall', 'Например: Остановить docker контейнер и удалить файлы...'),
('ru', 'ai', 'generate_script', 'Сгенерировать'),
('ru', 'ai', 'generating_script', 'Генерация...'),
('ru', 'ai', 'generated_script', 'Результат'),
('ru', 'ai', 'suggestions', 'Предложения'),
('ru', 'ai', 'apply_to_current_protocol', 'Применить'),
('ru', 'ai', 'confirm_apply_script', 'Это заменит текущее содержимое поля. Продолжить?'),
('ru', 'ai', 'please_enter_requirements', 'Пожалуйста, введите требования'),
('ru', 'ai', 'error_generating_script', 'Ошибка генерации')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
+10
View File
@@ -0,0 +1,10 @@
-- Add show_text_content column to protocols
ALTER TABLE protocols ADD COLUMN show_text_content TINYINT(1) NOT NULL DEFAULT 0;
-- Add translations
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en', 'protocols', 'show_text_content', 'Show text content on client page'),
('en', 'protocols', 'qr_code_format_text', 'Simple Text'),
('ru', 'protocols', 'show_text_content', 'Показывать текстовое содержимое на странице клиента'),
('ru', 'protocols', 'qr_code_format_text', 'Простой текст')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
+188
View File
@@ -0,0 +1,188 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Validate existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
# Check for unexpanded variables
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then
echo "Detected broken configuration (unexpanded variables). Removing..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for invalid parameters S3/S4
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf || grep -Eiq "^S4[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid parameters (S3/S4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for hex H-params
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid hex parameters (H1-H4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for empty PublicKey
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then
echo "Detected empty PublicKey. Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
fi
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
VPN_PORT=${PORT:-$VPN_PORT}
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
STATUS=1
elif [ $STATUS -eq 0 ]; then
echo "Container is running."
fi
# Ensure container is running
if [ $STATUS -ne 0 ]; then
echo "Starting container..."
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: $VPN_PORT"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey: $PSK"; fi
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
# Validate rescued config
IS_BROKEN=0
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if [ "$IS_BROKEN" = "1" ]; then
echo "Rescued config is broken. Discarding."
rm -f /opt/amnezia/awg/wg0.conf
else
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey: $PSK"; fi
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Use WG_CONF delimiter to avoid EOF replacement in PHP
cat > /opt/amnezia/awg/wg0.conf << WG_CONF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
H1 = 1
H2 = 2
H3 = 3
H4 = 4
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
WG_CONF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey: $PRESHARED_KEY"
'
WHERE slug = 'amnezia-wg-advanced';
+288
View File
@@ -0,0 +1,288 @@
UPDATE protocols SET
install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT=${VPN_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}
MTU=${MTU:-1420}
# Ensure host directory exists for persistence
mkdir -p /opt/amnezia/awg
# Function to check if container is healthy
check_container() {
local status
status=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "missing")
if [ "$status" = "running" ]; then
return 0
elif [ "$status" = "restarting" ]; then
return 2 # Restarting loop
else
return 1 # Stopped or missing
fi
}
# Validate existing config
if [ -f /opt/amnezia/awg/wg0.conf ]; then
# Check for unexpanded variables
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then
echo "Detected broken configuration (unexpanded variables). Removing..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for invalid parameters S3/S4
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf || grep -Eiq "^S4[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid parameters (S3/S4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for hex H-params
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then
echo "Detected invalid hex parameters (H1-H4). Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
# Check for empty PublicKey
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then
echo "Detected empty PublicKey. Removing config to regenerate..."
rm -f /opt/amnezia/awg/wg0.conf
fi
fi
# Check for existing configuration on HOST first (preferred persistence)
if [ -f /opt/amnezia/awg/wg0.conf ]; then
echo "Found existing configuration on host."
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
VPN_PORT=${PORT:-$VPN_PORT}
STATUS=0
check_container || STATUS=$?
if [ $STATUS -eq 2 ]; then
echo "Container is in restart loop. Recreating..."
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
STATUS=1
elif [ $STATUS -eq 0 ]; then
echo "Container is running."
fi
# Ensure container is running
if [ $STATUS -ne 0 ]; then
echo "Starting container..."
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
fi
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: $VPN_PORT"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey: $PSK"; fi
# Output variables for preview
echo "Variable: server_port=$VPN_PORT"
echo "Variable: server_public_key=$PUBKEY"
echo "Variable: preshared_key=$PSK"
echo "Variable: server_host=YOUR_IP"
# Dummy client vars for preview
CLIENT_PRIV_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
echo "Variable: private_key=$CLIENT_PRIV_KEY"
echo "Variable: client_ip=10.8.1.2"
echo "Variable: dns_servers=1.1.1.1"
# Obfuscation params (extract from config if possible, else defaults)
JC=$(grep -E "^Jc" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
JMIN=$(grep -E "^Jmin" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
JMAX=$(grep -E "^Jmax" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
S1=$(grep -E "^S1" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
S2=$(grep -E "^S2" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H1=$(grep -E "^H1" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H2=$(grep -E "^H2" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H3=$(grep -E "^H3" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H4=$(grep -E "^H4" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
echo "Variable: Jc=${JC:-5}"
echo "Variable: JC=${JC:-5}"
echo "Variable: Jmin=${JMIN:-100}"
echo "Variable: JMIN=${JMIN:-100}"
echo "Variable: Jmax=${JMAX:-200}"
echo "Variable: JMAX=${JMAX:-200}"
echo "Variable: S1=${S1:-50}"
echo "Variable: S2=${S2:-100}"
echo "Variable: H1=${H1:-1}"
echo "Variable: H2=${H2:-2}"
echo "Variable: H3=${H3:-3}"
echo "Variable: H4=${H4:-4}"
exit 0
fi
# Rescue logic
STATUS=0
check_container || STATUS=$?
HAS_RESCUED=0
if [ $STATUS -eq 2 ] || [ $STATUS -eq 0 ]; then
echo "Checking for config in existing container..."
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
if docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wg0.conf /opt/amnezia/awg/wg0.conf 2>/dev/null; then
# Validate rescued config
IS_BROKEN=0
if grep -Fq ''$PRIVATE_KEY'' /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^S3[[:space:]]*=" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^H[1-4][[:space:]]*=[[:space:]]*0x" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if grep -Eiq "^PublicKey[[:space:]]*=[[:space:]]*$" /opt/amnezia/awg/wg0.conf; then IS_BROKEN=1; fi
if [ "$IS_BROKEN" = "1" ]; then
echo "Rescued config is broken. Discarding."
rm -f /opt/amnezia/awg/wg0.conf
else
echo "Rescued config from container."
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_psk.key /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_public_key.key /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true
docker cp "$CONTAINER_NAME":/opt/amnezia/awg/wireguard_server_private_key.key /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true
HAS_RESCUED=1
fi
fi
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
fi
# Start container (Fresh or Rescued)
docker run -d --name "$CONTAINER_NAME" --restart always --privileged --cap-add=NET_ADMIN --cap-add=SYS_MODULE -p "${VPN_PORT}:${VPN_PORT}/udp" -v /lib/modules:/lib/modules -v /opt/amnezia/awg:/opt/amnezia/awg amneziavpn/amnezia-wg:latest sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; wg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
if [ "$HAS_RESCUED" = "1" ]; then
# Extract and exit
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey: $PSK"; fi
# Output variables for preview
echo "Variable: server_port=$VPN_PORT"
echo "Variable: server_public_key=$PUBKEY"
echo "Variable: preshared_key=$PSK"
echo "Variable: server_host=YOUR_IP"
# Dummy client vars for preview
CLIENT_PRIV_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
echo "Variable: private_key=$CLIENT_PRIV_KEY"
echo "Variable: client_ip=10.8.1.2"
echo "Variable: dns_servers=1.1.1.1"
# Obfuscation params (extract from config if possible, else defaults)
JC=$(grep -E "^Jc" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
JMIN=$(grep -E "^Jmin" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
JMAX=$(grep -E "^Jmax" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
S1=$(grep -E "^S1" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
S2=$(grep -E "^S2" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H1=$(grep -E "^H1" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H2=$(grep -E "^H2" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H3=$(grep -E "^H3" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
H4=$(grep -E "^H4" /opt/amnezia/awg/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
echo "Variable: Jc=${JC:-5}"
echo "Variable: JC=${JC:-5}"
echo "Variable: JMIN=${JMIN:-100}"
echo "Variable: Jmin=${JMIN:-100}"
echo "Variable: JMAX=${JMAX:-200}"
echo "Variable: Jmax=${JMAX:-200}"
echo "Variable: S1=${S1:-50}"
echo "Variable: S2=${S2:-100}"
echo "Variable: H1=${H1:-1}"
echo "Variable: H2=${H2:-2}"
echo "Variable: H3=${H3:-3}"
echo "Variable: H4=${H4:-4}"
exit 0
fi
# Generate new config
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# Use WG_CONF delimiter to avoid EOF replacement in PHP
cat > /opt/amnezia/awg/wg0.conf << WG_CONF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = 5
Jmin = 100
Jmax = 200
S1 = 50
S2 = 100
H1 = 1
H2 = 2
H3 = 3
H4 = 4
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
WG_CONF
echo "$PRIVATE_KEY" > /opt/amnezia/awg/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg/wireguard_psk.key
echo "[]" > /opt/amnezia/awg/clientsTable
echo "AmneziaWG Advanced installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey: $PRESHARED_KEY"
# Output variables for preview
echo "Variable: server_port=$VPN_PORT"
echo "Variable: server_public_key=$PUBLIC_KEY"
echo "Variable: preshared_key=$PRESHARED_KEY"
echo "Variable: server_host=YOUR_IP"
# Dummy client vars for preview
CLIENT_PRIV_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
echo "Variable: private_key=$CLIENT_PRIV_KEY"
echo "Variable: client_ip=10.8.1.2"
echo "Variable: dns_servers=1.1.1.1"
# Obfuscation params (hardcoded in new config)
echo "Variable: Jc=5"
echo "Variable: JC=5"
echo "Variable: Jmin=100"
echo "Variable: JMIN=100"
echo "Variable: Jmax=200"
echo "Variable: JMAX=200"
echo "Variable: S1=50"
echo "Variable: S2=100"
echo "Variable: H1=1"
echo "Variable: H2=2"
echo "Variable: H3=3"
echo "Variable: H4=4"
'
WHERE slug = 'amnezia-wg-advanced';
+5
View File
@@ -0,0 +1,5 @@
-- Fix AmneziaWG MTU to 1280 for better compatibility
-- This resolves connection issues with PPPoE, mobile networks, and tunnels
UPDATE protocols SET
install_script = REPLACE(install_script, 'MTU=${MTU:-1420}', 'MTU=${MTU:-1280}')
WHERE slug = 'amnezia-wg-advanced';
@@ -0,0 +1,52 @@
-- Fix AmneziaWG client config template: add MTU and use capital letter variables
UPDATE protocols SET
output_template = '[Interface]
PrivateKey = {{private_key}}
Address = {{client_ip}}/32
DNS = {{dns_servers}}
MTU = 1280
Jc = {{Jc}}
Jmin = {{Jmin}}
Jmax = {{Jmax}}
S1 = {{S1}}
S2 = {{S2}}
H1 = {{H1}}
H2 = {{H2}}
H3 = {{H3}}
H4 = {{H4}}
[Peer]
PublicKey = {{server_public_key}}
PresharedKey = {{preshared_key}}
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = {{server_host}}:{{server_port}}
PersistentKeepalive = 25'
WHERE slug = 'amnezia-wg-advanced';
-- Create capital letter variables that map to lowercase ones
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'Jc', 'number', '5', 'Junk packet count', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='Jc');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'Jmin', 'number', '100', 'Minimum junk packet size', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='Jmin');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'Jmax', 'number', '200', 'Maximum junk packet size', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='Jmax');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'S1', 'number', '50', 'Junk packet size 1', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='S1');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'S2', 'number', '100', 'Junk packet size 2', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='S2');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'H1', 'number', '1', 'Obfuscation header 1', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='H1');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'H2', 'number', '2', 'Obfuscation header 2', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='H2');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'H3', 'number', '3', 'Obfuscation header 3', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='H3');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'H4', 'number', '4', 'Obfuscation header 4', false FROM protocols p WHERE p.slug='amnezia-wg-advanced' AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id=p.id AND variable_name='H4');
@@ -0,0 +1,17 @@
-- Remove fully uppercase variable outputs from AmneziaWG install script
-- Keep only Jc, Jmin, Jmax format (first letter uppercase)
UPDATE protocols SET
install_script = REPLACE(
REPLACE(
REPLACE(
install_script,
'echo "Variable: JC=${JC:-5}"',
''
),
'echo "Variable: JMIN=${JMIN:-100}"',
''
),
'echo "Variable: JMAX=${JMAX:-200}"',
''
)
WHERE slug = 'amnezia-wg-advanced';
+1
View File
@@ -0,0 +1 @@
ALTER TABLE vpn_servers ADD COLUMN ssh_key TEXT NULL;