]> Git [git.vados.ru] :: Repos - Mikrotiks/ros.vados.ru.git/commitdiff
Autocommit in repo: ros.vados.ru, generated by owner: root, in 21:15:04 17.08.2026.
authorvados-dev <192440777+vados-dev@users.noreply.github.com>
Mon, 17 Aug 2026 18:15:05 +0000 (21:15 +0300)
committervados-dev <192440777+vados-dev@users.noreply.github.com>
Mon, 17 Aug 2026 18:15:05 +0000 (21:15 +0300)
html/.#AM-Fetch-Generator.rsc [deleted symlink]
html/AM-Fetch-Generator.rsc
html/AM-GlobalFunc.rsc

diff --git a/html/.#AM-Fetch-Generator.rsc b/html/.#AM-Fetch-Generator.rsc
deleted file mode 120000 (symlink)
index af090d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-root@amster.3712
\ No newline at end of file
index 03034e99c4ba544958359ba6e211df28cac626f0..e79b6c0c5f76864d5a3ebc6f0079371c134eb341 100644 (file)
-#!rsc by Vados\r
-# RouterOS script: AM-Backup-UpdateEmail\r
-# Script comment: Update and Backup send notification to EMail\r
-# Copyright (c) 2007-2026 Vados <vados@vados.ru>\r
-#\r
-#\r
-# requires RouterOS, version>=6.43.7\r
-# requires device-mode, fetch\r
-#\r
-# Updated: 15/04/2025\r
-# Website: https://github.com/beeyev\r
-# Notification e-mail (Make sure you have configured Email settings in Tools -> Email)\r
-:local ExitOK false;\r
-:onerror Err {\r
-  :global GlobalConfReady; :global GlobalFuncReady;\r
-  :retry { :if ($GlobalConfReady != true || $GlobalFuncReady != true) \\r
-      do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;\r
-  :local ScriptName [ :jobname ];\r
-\r
-:local IfThenElse do={:if ([ :tostr $1 ] = "true" || [ :tobool $1 ] = true) do={:return $2}; :return $3;}\r
-:local EitherOr do={\r
-  :if ([ :typeof $1 ] = "num") do={:if (($1 != 0) = true) do={:return $1} else={:return $2};}\r
-  :if ([ :typeof $1 ] = "time") do={:if (($1 > 0s) = true) do={:return $1} else={:return $2};}\r
-  :if ([ :len [ :tostr $1 ] ] > 0) do={:return $1} else={:return $2};\r
-}\r
-:local ExitError do={\r
-  :local ExitOK [ :tostr $1 ];\r
-  :local Name   [ :tostr $2 ];\r
-  :local Error  [ :tostr $3 ];\r
-  :if ($ExitOK = "false") do={:log error ($Name [ $IfThenElse ([ :pick $Name 0 1 ] = "\$") \\r
-        "Function" "Script" ] . " '" . $Name . "' exited with error" . \\r
-        [ $IfThenElse (!($Error ~ "^(|true|false)\$")) (": " . $Error) "." ]);}\r
-}\r
-\r
-:global LogPrint;\r
-:global EditSchedulers;\r
-:global DevInfoIncludeIP;\r
-\r
-:local SchedInterval "7d";\r
-:local SchedStartTime "03:41:27";\r
-:local SchedComment "Every 7 Day Check For Update and Backup send notification to EMail.";\r
-\r
-# Function to add or edit schedulers for scripts, to ensure they are set up correctly\r
-# How to use:\r
-# Call this function with the following parameters:\r
-# 1. $1 - Scheduler name (usually same as script name) [*]\r
-# 2. $2 - Interval (e.g. "1d" (default is "1d")) [**]\r
-# 3. $3 - Start Time (e.g. "00:00:00", default is current time) [**]\r
-# 4. $4 - Comment (optional, default: "Scheduler for script: <name>") [**]\r
-# 5. $5 - On Event command (e.g. "/system/script { run <name>; }" (default is "/system/script { run $SchedName; }")) [**]\r
-# 6. $6 - Policy (e.g. "ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon" (default is the same)) [**]\r
-# 7. $7 - Start Date (e.g. "jan/01/1970", default is current date) [**]\r
-# Notes:\r
-# *  - Scheduler name is required, and is used to identify the scheduler to create or edit. It is usually the same as the script name ($ScriptName).\r
-# ** - If optional parameters are not provided, default values will be used.\r
-#      This allows for quick setup with minimal parameters, while still providing flexibility for customization.\r
-# Example usage:\r
-# :if ([ $EditSchedulers "my-script" ] = false) do={:set ExitOK false; :error true;}\r
-# :if ([ $EditSchedulers "my-script" "1d" "03:41:27" "My custom scheduler comment" false false "jan/01/1970" ] = false) do={:set ExitOK false; :error true;}\r
-\r
-:set EditSchedulers do={\r
-  :local SchedName [ :tostr $1 ];\r
-  :if ([ :len $SchedName ] = 0) do={ :return false; }\r
-  :local Interval [ :tostr $2 ];\r
-  :if ([ :len $Interval ] = 0) do={ :set Interval "1d"; }\r
-  :local StartTime [ :tostr $3 ];\r
-  :if ([ :len $StartTime ] = 0) do={ :set StartTime [/system/clock/get time]; }\r
-  :local Comment [ :tostr $4 ];\r
-  :if ([ :len $Comment ] = 0) do={ :set Comment "Scheduler for script: $SchedName"; }\r
-  :local OnEvent [ :tostr $5 ];\r
-  :if ([ :len $OnEvent ] = 0) do={ :set OnEvent "/system/script { run $SchedName; }"; }\r
-  :local Policy [ :tostr $6 ];\r
-  :if ([ :len $Policy ] = 0) do={ :set Policy "ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon"; }\r
-  :local StartDate [ :tostr $7 ];\r
-  :if ([ :len $StartDate ] = 0) do={ :set StartDate [/system/clock/get date]; }\r
-\r
-  :onerror Err {\r
-    # Check if scheduler exists, if not - create it\r
-    :if ([ :len [ /system/scheduler/find where name=$SchedName ] ] = 0) do={\r
-      :log warning ($SchedName . "System Scheduler for script: " . $SchedName . " is NOT SET! Fix It Now!");\r
-      /system/scheduler/add comment=$Comment interval=$Interval name=$SchedName on-event=$OnEvent policy=$Policy start-date=$StartDate start-time=$StartTime;\r
-    }\r
-    # Check if scheduler parameters are correct, if not - fix them\r
-    :if ([ /system/scheduler/get $SchedName comment ] != $Comment) do={\r
-      /system/scheduler/set $SchedName comment=$Comment;\r
-    }\r
-    :if ([ /system/scheduler/get $SchedName interval ] != $Interval) do={\r
-      /system/scheduler/set $SchedName interval=$Interval;\r
-    }\r
-    :if ([ /system/scheduler/get $SchedName on-event ] != $OnEvent) do={\r
-      /system/scheduler/set $SchedName on-event=$OnEvent;\r
-    }\r
-    :if ([ /system/scheduler/get $SchedName policy ] != $Policy) do={\r
-      /system/scheduler/set $SchedName policy=$Policy;\r
-    }\r
-    :if ([ /system/scheduler/get $SchedName start-date ] != $StartDate) do={\r
-      /system/scheduler/set $SchedName start-date=$StartDate;\r
-    }\r
-    :if ([ /system/scheduler/get $SchedName start-time ] != $StartTime) do={\r
-      /system/scheduler/set $SchedName start-time=$StartTime;\r
-    }\r
-  } do={:log error ($SchedName . "Failed to add/modify scheduler for '" . $SchedName . "' failed: " . $Err); :return false};\r
-    :return true;\r
-}\r
-\r
-:if ([ $EditSchedulers $ScriptName $SchedInterval $SchedStartTime $SchedComment ] = false) do={\r
-  :log error ($ScriptName . "Failed to add/modify scheduler for " . $ScriptName . "!");\r
-  :set ExitOK true;\r
-  :error true;\r
-}\r
-\r
-# Local Function CheckOSUpdateMode\r
-:local CheckOSUpdateMode;\r
-:set CheckOSUpdateMode do={\r
-  :local NewMode [ :tostr $1 ];\r
-  :if ([ :len $NewMode ] = 0) do={\r
-    :log error ($0 . "/nFunction /$CheckOSUpdateMode received empty value!");\r
-    :return false;\r
-    :error true;\r
-  }\r
-\r
-  :global BackupAndUpdateMode;\r
-  :global OldMode [ :tostr $BackupAndUpdateMode ];\r
-  :if ($NewMode != $BackupAndUpdateMode && $NewMode = "updateOnce") do={\r
-    :set BackupAndUpdateMode [ :tostr $NewMode ];\r
-    :log info ($0 . "/nOk. /$BackupAndUpdateMode set to: '" . $NewMode . "'.\nYou're a good boy! ))\nI'm launching the update in 5 seconds.");\r
-    :delay 5;\r
-    /system/script { run $ScriptName; };\r
-  } else={\r
-  :log warning ($0 . "/nFunction /$CheckOSUpdateMode received value: '" . $NewMode . "', but is may be only \"updateOnce\"!");\r
-  :return false;\r
-  }\r
-  :return true;\r
-  :error false;\r
-}\r
-\r
-#  :if ([ :len [ /system/scheduler/find where name="running-from-backup-partition" ] ] > 0) do={\r
-#    $LogPrint warning $ScriptName ("Running from backup partition, refusing to act.");\r
-#    :set ExitOK true;\r
-#    :error false;\r
-#  }\r
-\r
-:global EmailGeneralTo;\r
-:global BackupAndUpdateMode;\r
-:global forceBackup;\r
-:global BackupPassword;\r
-:global BackupSens;\r
-:global updateChannel;\r
-\r
-:global DevInfoIncludeIP;\r
-\r
-# Installs patch updates only (BackupAndUpdateMode = "osupdate").\r
-# Works for `stable` and `long-term` channels.\r
-# Updates only if MAJOR.MINOR match (e.g. 6.43.2 > 6.43.6 allowed, 6.44.1 skipped).\r
-# Sends info if a newer (non-patch) version is found.\r
-:local installOnlyPatchUpdates false;\r
-:local scriptVersion "26.04.30";\r
-:local copyrightUrl "https://www.github.com/vados-dev/";\r
-#Script messages prefix\r
-:local SMP "BkpAndUpdate:";\r
-\r
-:local exitErrorMessage "$SMP script stopped due to an error. Please check logs for more details.";\r
-:log info "\n\n$SMP Script \"Mikrotik RouterOS automatic backup & update\" v.$scriptVersion started.";\r
-:log info "$SMP Script Mode: `$BackupAndUpdateMode`, Update channel: `$updateChannel`, Force backup: `$forceBackup`, Install only patch updates: `$installOnlyPatchUpdates`";\r
-\r
-## vv FUNCTIONS vv ##\r
-:global WaitCheckUpdates; $WaitCheckUpdates;\r
-:global MiniDateTimeStamp;\r
-:local MDTSFix [$MiniDateTimeStamp];\r
-:global Identity;\r
-:global IdentityShort;\r
-:global devBoardName;\r
-:global runningVersion;\r
-:global runningChannel;\r
-:global devModel;\r
-:global devRbSerialNumber;\r
-:global ROsVerAvail;\r
-:global PkgUpdStatus;\r
-\r
-# Checks if two RouterOS version strings differ only by the patch version\r
-# :put [$FuncIsPatchUpdateOnly "6.2.1" "6.2.4"]  # Output: true\r
-# :put [$FuncIsPatchUpdateOnly "6.2.1" "6.3.1"]  # Output: false\r
-:local FuncIsPatchUpdateOnly do={\r
-  :local ver1 $1;\r
-  :local ver2 $2;\r
-  # Extract the major and minor components from a version\r
-  :local extractMajorMinor do={\r
-    :local ver $1;\r
-    :local dot1 [:find $ver "."];\r
-    :if ($dot1 = -1) do={:return $ver}\r
-    :local major [:pick $ver 0 $dot1];\r
-    :local rest [:pick $ver ($dot1 + 1) [:len $ver]];\r
-    :local dot2 [:find $rest "."];\r
-    :local minor $rest;\r
-    :if ($dot2 >= 0) do={:set minor [:pick $rest 0 $dot2]}\r
-    :return ($major . "." . $minor);\r
-  }\r
-\r
-# Compare the major and minor components of both version strings\r
-:if ([$extractMajorMinor $ver1] = [$extractMajorMinor $ver2]) do={:return true}\r
- :return false;\r
-}\r
-# Creates backups and returns array of names\r
-# Possible arguments:\r
-#  $1 - file name, without extension\r
-#  $2 - password (optional)\r
-#  $3 - sensitive data in config (optional, default: false)\r
-# Example:\r
-#:put [$FuncCreateBackups $backupName]\r
-:local FuncCreateBackups do={\r
-  :local backupName [ :tostr $1 ];\r
-  :local BackPass $2;\r
-  :local BackSens $3;\r
-\r
-  #Script messages prefix\r
-  :local SMP "BkpAndUpdate:";\r
-  :local exitErrorMessage "$SMP script stopped due to an error. Please check logs for more details.";\r
-  :log info ("$SMP global function `FuncCreateBackups` started, input: `$backupName`");\r
-\r
-  # validate required parameter: backupName\r
-  :if ([:typeof $backupName] != "str" or [:len $backupName] = 0) do={\r
-    :log error "$SMP parameter 'backupName' is required and must be a non-empty string";\r
-#    :log warning "$SMP parameter '\$backupName' is required and must be a non-empty string.\nI set '\$backupName' to 'default-backup'";\r
-#    :set $backupName "default-backup";\r
-    :error $exitErrorMessage;\r
-  }\r
-\r
-  :local backupFileSys "$backupName.backup";\r
-  :local backupFileConfig "$backupName.rsc";\r
-  :local backupNames {$backupFileSys;$backupFileConfig};\r
-\r
-  ## Perform system backup\r
-  :if ([:len $BackPass] = 0) do={\r
-    :log info ("$SMP starting backup without password, backup name: `$backupName`");\r
-    /system backup save dont-encrypt=yes name=$backupName;\r
-  } else={\r
-    :log info ("$SMP starting backup with password, backup name: `$backupName`");\r
-    /system backup save password=$BackPass name=$backupName;\r
-  }\r
-  :log info ("$SMP system backup created: `$backupFileSys`");\r
-    ## Export config file\r
-  :if ($BackSens = true) do={\r
-    :log info ("$SMP starting export config with sensitive data, backup name: `$backupName`");\r
-    # Since RouterOS v7 it needs to be explicitly set that we want to export sensitive data\r
-    :if ([:pick [/system resource get version] 0 1] < 7) do={\r
-      :execute "/export compact terse file=$backupName";\r
-    } else={\r
-      :execute "/export compact show-sensitive terse file=$backupName";\r
-    }\r
-  } else={\r
-    :log info ("$SMP starting export config without sensitive data, backup name: `$backupName`");\r
-    /export compact hide-sensitive terse file=$backupName;\r
-  }\r
-  :log info ("$SMP Config export complete: `$backupFileConfig`");\r
-  :log info ("$SMP Waiting a little to ensure backup files are written");\r
-  :delay 20;\r
-  :if ([:len [/file find name=$backupFileSys]] > 0) do={\r
-    :log info ("$SMP system backup file successfully saved to the file system: `$backupFileSys`");\r
-  } else={\r
-    :log error ("$SMP system backup was not created, file does not exist: `$backupFileSys`");\r
-    :error $exitErrorMessage;\r
-  }\r
-  :if ([:len [/file find name=$backupFileConfig]] > 0) do={\r
-    :log info ("$SMP config backup file successfully saved to the file system: `$backupFileConfig`");\r
-  } else={\r
-    :log error ("$SMP config backup was not created, file does not exist: `$backupFileConfig`");\r
-    :error $exitErrorMessage;\r
-  }\r
-  :log info ("$SMP global function `FuncCreateBackups` finished. Created backups, system: `$backupFileSys`, config: `$backupFileConfig`")\r
-  :return $backupNames;\r
-}\r
-# Sends an email\r
-# Parameters:\r
-#  $1 - to (email address)\r
-#  $2 - subject\r
-#  $3 - body\r
-#  $4 - file attachments (optional; pass "" if not needed)\r
-#\r
-# Example:\r
-# $FuncSendEmailSafe "admin@domain.com" "Backup Done" "Backup complete." "backup1.backup"\r
-:local FuncSendEmailSafe do={\r
-  :global EmailGeneralTo;\r
-  :local emailSubject $2;\r
-  :local emailBody $3;\r
-  :local emailAttachments $4;\r
-  :local SMP "Bkp&Upd:";\r
-  :local exitErrorMessage "$SMP script stopped due to an error. Please check logs for more details.";\r
-  :log info "$SMP Attempting to send email to `$EmailGeneralTo`";\r
-  # SAFETY: wait for any previously queued email to finish\r
-  :local waitTimeoutPre 60;\r
-  :local waitCounterPre 0;\r
-  :while (([/tool e-mail get last-status] = "resolving-dns" or [/tool e-mail get last-status] = "in-progress")) do={\r
-    :if ($waitCounterPre >= $waitTimeoutPre) do={\r
-      :log error "$SMP Email send aborted: previous send did not complete after $waitTimeoutPre seconds";\r
-      :error $exitErrorMessage;\r
-    }\r
-    :log info "$SMP Waiting for previous email to finish (status: $[/tool e-mail get last-status])...";\r
-    :delay 1; \r
-    :set waitCounterPre ($waitCounterPre + 1);\r
-  }\r
-  # Send the email\r
-  :do {\r
-    /tool e-mail send to=$EmailGeneralTo subject=$emailSubject body=$emailBody file=$emailAttachments;\r
-  } on-error={\r
-    :log error "$SMP Email send command failed to execute. Check logs and verify email settings.";\r
-    :error $exitErrorMessage;\r
-  }\r
-  # Wait for send status to change from "in-progress" / "resolving-dns"\r
-  :local waitTimeout 60;\r
-  :local waitCounter 0;\r
-  :local emailStatus "";\r
-  :log info "$SMP Waiting for email to be sent, timeout in `$waitTimeout` seconds...";\r
-  :while ($waitCounter < $waitTimeout) do={\r
-    :set emailStatus [/tool e-mail get last-status];\r
-    :if ($emailStatus != "in-progress" and $emailStatus != "resolving-dns") do={\r
-      :log info "$SMP Email send status received: $emailStatus";\r
-      # exit loop\r
-      :set waitCounter $waitTimeout;\r
-    } else={:delay 1; :set waitCounter ($waitCounter + 1)}\r
-  }\r
-  # Final decision based on last status\r
-  :if ($emailStatus = "succeeded") do={\r
-    :log info  "$SMP Email successfully sent to `$EmailGeneralTo`";\r
-  } else={\r
-    :log error "$SMP Email failed to send. Status: `$emailStatus`. Check logs for more details and verify email settings.";\r
-    :error $exitErrorMessage;\r
-  }\r
-}\r
-# Global variable to track current update step\r
-# They need to be initialized here first to be available in the script\r
-:global buGlobalVarTargetOsVersion;\r
-:global buGlobalVarScriptStep;\r
-:local scriptStep $buGlobalVarScriptStep;\r
-:do {\r
-  /system/script/environment remove buGlobalVarScriptStep;\r
-} on-error={}\r
-:if ([:len $scriptStep] = 0) do={\r
-  :set scriptStep 1;\r
-}\r
-## ^^ FUNCTIONS ^^ ##\r
-#\r
-# Initial validation\r
-## Check email settings\r
-:if ([:len $EmailGeneralTo] < 3) do={\r
-  :log error ("$SMP Parameter `\$EmailGeneralTo` is not set, or contains invalid value. Script stopped.");\r
-  :error $exitErrorMessage;\r
-}\r
-# Values will be defined later in the script\r
-:local emailServer "";\r
-:local emailFromAddress [/tool e-mail get from];\r
-:log info "$SMP Validating email settings...";\r
-:do {\r
-  :set emailServer [/tool e-mail get server];\r
-} on-error={\r
-  # This is a workaround for the RouterOS v7.12 and older versions\r
-  :set emailServer [/tool e-mail get address];\r
-}\r
-:if ($emailServer = "0.0.0.0") do={\r
-  :log error ("$SMP Email server address is not correct: `$emailServer`, check `Tools -> Email`. Script stopped.");\r
-  :error $exitErrorMessage;\r
-}\r
-:if ([:len $emailFromAddress] < 3) do={\r
-  :log error ("$SMP Email configuration FROM address is not correct: `$emailFromAddress`, check `Tools -> Email`. Script stopped.");\r
-  :error $exitErrorMessage;\r
-}\r
-# Script mode validation\r
-:if ($BackupAndUpdateMode != "backup" and $BackupAndUpdateMode != "osupdate" and $BackupAndUpdateMode != "updateOnce" and $BackupAndUpdateMode != "osnotify") do={\r
-  :log error ("$SMP Script parameter `\$BackupAndUpdateMode` is not set, or contains invalid value: `$BackupAndUpdateMode`. Script stopped.");\r
-  :error $exitErrorMessage;\r
-}\r
-# Update channel validation\r
-:if ($updateChannel != "stable" and $updateChannel != "long-term" and $updateChannel != "testing" and $updateChannel != "development") do={\r
-  :log error ("$SMP Script parameter `\$updateChannel` is not set, or contains invalid value: `$updateChannel`. Script stopped.");\r
-  :error $exitErrorMessage;\r
-}\r
-# Verify if script is set to install patch updates and if the update channel is valid\r
-:if (($BackupAndUpdateMode = "osupdate" or $BackupAndUpdateMode = "updateOnce") and $installOnlyPatchUpdates = true) do={\r
-  :if ($updateChannel != "stable" and $updateChannel != "long-term") do={\r
-    :log error ("$SMP Patch-only updates enabled, but update channel `$updateChannel` is invalid. Only `stable` and `long-term` are supported. Script stopped");\r
-    :error $exitErrorMessage;\r
-  }\r
-  \r
-  :if ($runningChannel != "stable" and $runningChannel != "long-term") do={\r
-    :log error ("$SMP Script is set to install only patch updates, but the installed RouterOS version is not from `stable` or `long-term` channel: `$runningChannel`. Script stopped");\r
-    :error $exitErrorMessage;\r
-  }\r
-}\r
-#\r
-\r
-:local rawTime [/system clock get time];\r
-:local rawDate [/system clock get date];\r
-\r
-:local deviceOsVerAndChannelRunning [/system/resource/get version];\r
-\r
-:local backupNameTemplate     ("backup_v" . $runningVersion . "_" . $runningChannel . "_" . $MDTSFix);\r
-:local backupNameBeforeUpdate ($backupNameTemplate . "_before_update");\r
-:local backupNameAfterUpdate  ($backupNameTemplate . "_after_update");\r
-\r
-## Email body template\r
-:local mailSubjectPrefix  "$SMP Device - `$IdentityShort`";\r
-:local mailBodyCopyright  "Mikrotik RouterOS automatic backup & update (ver. $scriptVersion) \n$copyrightUrl";\r
-:local changelogUrl     "Check RouterOS changelog: https://mikrotik.com/download/changelogs/";\r
-:local mailBodyDeviceInfo  "";\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "Device information:");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\n---------------------");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nName: $Identity");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nModel: $devModel");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nBoard: $devBoardName");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nSerial number: $devRbSerialNumber");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nRouterOS version: v$deviceOsVerAndChannelRunning");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nBuild time: $[/system/resource/get build-time]");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nRouterboard FW Available: $ROsVerAvail");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nDevice date-time: $rawDate $rawTime ($[/system/clock/get time-zone-name ])");\r
-:set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nUptime: $[/system/resource/get uptime]");\r
-## IP address detection\r
-:if ([ $DevInfoIncludeIP ] = true) do={\r
-  :global GetPubIp;\r
-  :local PublicIpAddress [ $GetPubIp ];\r
-  :set mailBodyDeviceInfo ($mailBodyDeviceInfo . "\nPublic IP address: " . $PublicIpAddress . ".");\r
-  :log info "$SMP Public IP address detected: $PublicIpAddress";\r
-}  \r
-\r
-:local mailAttachments  [:toarray ""];\r
-:if ($scriptStep = 1 or $scriptStep = 3) do={\r
-  :if ($scriptStep = 3) do={\r
-    :log info ("$SMP Waiting for one minute before continuing to the final step.");\r
-    :delay 1m;\r
-  }\r
-}\r
-\r
-## STEP 1: Create backups, check for new RouterOS, and send email\r
-## Steps 2â3 run only if auto-update is enabled and a new version is available\r
-:if ($scriptStep = 1) do={\r
-  :global BackupPassword;\r
-  :global BackupSens;\r
-  :local isNewOsUpdateAvailable false;\r
-  :local isLatestOsAlreadyInstalled true;\r
-  :local isOsNeedsToBeUpdated false;\r
-  :local isUpdateCheckSucceeded false;\r
-  :local isEmailNeedsToBeSent false;\r
-  :local mailSubjectPartAction "";\r
-  :local mailPtBodyAction "";\r
-  :local mailPtSubjectBackup "";\r
-  :local mailPtBodyBackup "";\r
-  # Checking for new version\r
-  :if ($BackupAndUpdateMode = "osupdate" or $BackupAndUpdateMode = "osnotify" or $BackupAndUpdateMode = "updateOnce") do={\r
-    :log info ("$SMP Setting update channel to `$updateChannel`");\r
-     /system/package/update/set channel=$updateChannel;\r
-    :log info ("$SMP Checking for new RouterOS version. Current installed version is: `$runningVersion`");\r
-      $LogPrint debug $ScriptName ("Checking for updates...");\r
-      \r
-#     /system/package/update/check-for-updates without-paging as-value;\r
-#     /system/package/update check-for-updates;\r
-    :delay 5s;\r
-    :set PkgUpdStatus [ /system/package/update/get status ];\r
-    :if ($PkgUpdStatus = "New version is available") do={\r
-    :set ROsVerAvail [/system/package/update/get latest-version];\r
-    }\r
-\r
-    :if ($PkgUpdStatus = "New version is available") do={\r
-      :log info ("$SMP New RouterOS version is available: `$ROsVerAvail`");\r
-      :set isNewOsUpdateAvailable true;\r
-      :set isLatestOsAlreadyInstalled false;\r
-      :set isUpdateCheckSucceeded true;\r
-      :set isEmailNeedsToBeSent true;\r
-      :set mailSubjectPartAction "New RouterOS available";\r
-      :set mailPtBodyAction  "New RouterOS version is available, current version: v$runningVersion, new version: v$ROsVerAvail. \n$changelogUrl";\r
-    } else={\r
-      :if ($PkgUpdStatus = "System is already up to date") do={\r
-        :log info ("$SMP No new RouterOS version is available, the latest version is already installed: `v$runningVersion`");\r
-        :set isUpdateCheckSucceeded true;\r
-        :set mailSubjectPartAction "No os update available";\r
-        :set mailPtBodyAction  "No new RouterOS version is available, the latest version is already installed: `v$runningVersion`";\r
-      } else={\r
-        :log error ("$SMP Failed to check for new RouterOS version. Package check status: `$PkgUpdStatus`");\r
-        :set isEmailNeedsToBeSent true;\r
-        :set mailSubjectPartAction "Error unable to check new os version";\r
-        :set mailPtBodyAction  "An error occurred while checking for a new RouterOS version.\nStatus returned: `$PkgUpdStatus`\n\nPlease review the logs on the device for more details and verify internet connectivity.";\r
-      }\r
-    }\r
-  }\r
-  # Checking if the script needs to install new os version\r
-  :if (($BackupAndUpdateMode = "osupdate" or $BackupAndUpdateMode = "updateOnce") and $isNewOsUpdateAvailable = true) do={\r
-    :if ($installOnlyPatchUpdates = true) do={\r
-      :if ([$FuncIsPatchUpdateOnly $runningVersion $ROsVerAvail] = true) do={\r
-        :log info "$SMP New RouterOS version is available, and it is a patch update. Current version: v$runningVersion, new version: v$ROsVerAvail";\r
-        :set isOsNeedsToBeUpdated true;\r
-      } else={\r
-        :log info "$SMP The script will not install this update, because it is not a patch update. Current version: v$runningVersion, new version: v$ROsVerAvail";\r
-        :set mailPtBodyAction ($mailPtBodyAction . "\nThis update will not be installed, because the script is set to install only patch updates.");\r
-      }\r
-    } else={\r
-      :set isOsNeedsToBeUpdated true;\r
-      }\r
-  }\r
-  # Checking If the script needs to create a backup\r
-  :if ($forceBackup = true or $BackupAndUpdateMode = "backup" or $isOsNeedsToBeUpdated = true) do={\r
-    :log info ("$SMP Starting backup process.");\r
-    :set isEmailNeedsToBeSent true;\r
-    :local backupName $backupNameTemplate;\r
-    # This means it's the first step where we create a backup before the update process\r
-    :if ($isOsNeedsToBeUpdated = true) do={\r
-      :set backupName $backupNameBeforeUpdate;\r
-      #Email body if the purpose of the script is to update the device\r
-      :set mailSubjectPartAction "Update preparation";\r
-      :set mailPtBodyAction ($mailPtBodyAction . "\nThe update process for device '$Identity' is scheduled to upgrade RouterOS from version v.$runningVersion to version v.$ROsVerAvail (Update channel: $updateChannel)");\r
-      :set mailPtBodyAction ($mailPtBodyAction . "\nPlease note: The update will proceed only after a successful backup.");\r
-      :set mailPtBodyAction ($mailPtBodyAction . "\nA final report with detailed information will be sent once the update process is completed.");\r
-      :set mailPtBodyAction ($mailPtBodyAction . "\nIf you do not receive a second email within the next 10 minutes, there may be an issue. Please check your device logs for further information.");\r
-    }\r
-    :do {\r
-      :set mailAttachments [$FuncCreateBackups $backupName $BackupPassword $BackupSens];\r
-      :set mailPtSubjectBackup "Backup created";\r
-      :set mailPtBodyBackup "System backups have been successfully created and attached to this email.";\r
-    } on-error={\r
-      :set isOsNeedsToBeUpdated false;\r
-      :set mailPtSubjectBackup "Backup failed";\r
-      :set mailPtBodyBackup "The script failed to create backups. Please check device logs for more details.";\r
-      :log warning "$SMP Backup creation failed. Update process will be canceled if automatic update is enabled";\r
-    }\r
-  }\r
-  :if ($isEmailNeedsToBeSent = true) do={\r
-    :log info "$SMP Preparing to send email...";\r
-    :local mailStep1Subject $mailSubjectPrefix;\r
-    :local mailStep1Body  "";\r
-    # subject\r
-    :if ($mailSubjectPartAction != "")  do={:set mailStep1Subject ($mailStep1Subject . " - " . $mailSubjectPartAction)}\r
-    :if ($mailPtSubjectBackup != "")  do={:set mailStep1Subject ($mailStep1Subject . " - " . $mailPtSubjectBackup)}\r
-    # body\r
-    :if ($mailPtBodyAction != "") do={:set mailStep1Body ($mailStep1Body . $mailPtBodyAction . "\n\n")}\r
-    :if ($mailPtBodyBackup != "") do={:set mailStep1Body ($mailStep1Body . $mailPtBodyBackup . "\n\n")}\r
-    :set mailStep1Body ($mailStep1Body . $mailBodyDeviceInfo . "\n__________\n" . $mailBodyCopyright);\r
-    :set mailStep1Body ($mailStep1Body . "\n[*** TEST START ***]\n\$DeviceInfo: " . [ $DeviceInfo ] . "\n[*** TEST END ***]\n");\r
-    # Send email with backups\r
-    :do {$FuncSendEmailSafe $EmailGeneralTo $mailStep1Subject $mailStep1Body $mailAttachments} on-error={\r
-      :set isOsNeedsToBeUpdated false;\r
-      :log error "$SMP The script will not proceed with the update process, because the email was not sent.";\r
-    }\r
-  }\r
-  :if ([:len $mailAttachments] > 0) do={\r
-    :log info "$SMP Cleaning up backup files from the file system...";\r
-    /file remove $mailAttachments;\r
-    :delay 2s;\r
-  }\r
-  :if ($isOsNeedsToBeUpdated = true) do={\r
-    :global OldMode;\r
-    :log info "$SMP everything is ready to install new RouterOS, going to start the update process and reboot the device.";\r
-    :do {\r
-      :local nextStep 2;\r
-      :if ($isCloudHostedRouter = true) do={\r
-        :log info "$SMP The device is a cloud hosted router, the second step updating the Routerboard firmware will be skipped.";\r
-        :set nextStep 3;\r
-      }\r
-      :local scheduledCommand (":delay 5s; /system/scheduler remove BKPUPD-NEXT-BOOT-TASK; \\r
-       :global buGlobalVarScriptStep $nextStep; :global buGlobalVarTargetOsVersion \"$ROsVerAvail\"; \\r
-      :delay 10s; /system/script { run $ScriptName; }");\r
-      /system/scheduler add name=BKPUPD-NEXT-BOOT-TASK on-event=$scheduledCommand start-time=startup interval=0;\r
-      /system/package/update install;\r
-     } on-error={\r
-      # Failed to install new os version, remove the task and variables\r
-      :do {\r
-        /system/scheduler remove BKPUPD-NEXT-BOOT-TASK;\r
-        :set BackupAndUpdateMode $OldMode;\r
-        :delay 2;\r
-        :do {\r
-          :global buGlobalVarTargetOsVersion (a);\r
-        } on-error={\r
-          :set $mailSubjectPrefix ($mailSubjectPrefix . "ERROR Remove global variable \$buGlobalVarTargetOsVersion failed!");\r
-        }\r
-#        :if ([ :len $OldMode ] > 0) do={\r
-#          :do {\r
-#           :global OldMode (a);\r
-#          } on-error={\r
-#            :set $mailSubjectPrefix ($mailSubjectPrefix . " ERROR Remove global variable \$OldMode failed!");\r
-#          }\r
-#        }\r
-      } on-error={\r
-        :log error "$SMP Failed to install new RouterOS version. Please check device logs for more details. \\r
-        \nAnd Failed to remove task and variables! Check it!";\r
-        :set $mailSubjectPrefix ($mailSubjectPrefix . " ERROR Remove task and global variables!");\r
-      }\r
-      :log error "$SMP Failed to install new RouterOS version. Please check device logs for more details.";\r
-      :local mailUpdateErrorSubject ($mailSubjectPrefix . " - Update failed");\r
-      :local mailUpdateErrorBody "The script was unable to install new RouterOS version. Please check device logs for more details.";\r
-      # Send email with error\r
-      $FuncSendEmailSafe $EmailGeneralTo $mailUpdateErrorSubject $mailUpdateErrorBody "";\r
-      :error $exitErrorMessage;\r
-    }\r
-  }\r
-}\r
-## STEP 2: (Post-reboot) Upgrade RouterBOARD firmware\r
-## Runs only if auto-update is enabled and a new RouterOS version was found\r
-:if ($scriptStep = 2) do={\r
-  :log info "$SMP The script is in the second step, updating Routerboard firmware.";\r
-  :log info "$SMP Upgrading routerboard firmware from v.$deviceRbCurrentFw to v.$deviceRbUpgradeFw";\r
-  /system routerboard upgrade;\r
-  :delay 2;\r
-  :log info "$SMP routerboard upgrade process was completed, going to reboot in a moment!";\r
-  ## Set task to send final report on the next boot\r
-  /system scheduler add name=BKPUPD-NEXT-BOOT-TASK on-event=":delay 2; :global buGlobalVarScriptStep 3; \\r
-   :global buGlobalVarTargetOsVersion \"$buGlobalVarTargetOsVersion\"; :delay 10s; /system/script { run $ScriptName; }; \ \r
-   :delay 5s; /system/scheduler remove BKPUPD-NEXT-BOOT-TASK;" start-time=startup interval=0;\r
-   :delay 2;\r
-  /system reboot;\r
-}\r
-\r
-## STEP 3: Final report (after second reboot, with delay).\r
-## Runs only if auto-update is enabled and a new RouterOS version was found.\r
-:if ($scriptStep = 3) do={\r
-  :log info ("$SMP The script is in the third step, sending final report.");\r
-  :local targetOsVersion $buGlobalVarTargetOsVersion;\r
-  :do {\r
-#    /system/script/environment remove [find name="buGlobalVarTargetOsVersion"];\r
-    :global buGlobalVarTargetOsVersion (a);\r
-  } on-error={\r
-    :set $mailSubjectPrefix ($mailSubjectPrefix . " ERROR Remove global variable \$buGlobalVarTargetOsVersion failed!");\r
-  }\r
-\r
-  :if ([ :len $OldMode ] != 0) do={\r
-    :do {\r
-#      /system/script/environment remove [find name="OldMode"];\r
-      :global OldMode (a);\r
-      } on-error={\r
-        :set $mailSubjectPrefix ($mailSubjectPrefix . " ERROR! Remove global variable \$OldMode failed!");\r
-       }\r
-  }\r
-  :if ([:len $targetOsVersion] = 0) do={\r
-    :log warning "$SMP Something is wrong, the script was unable to get the target updated OS version from the global variable.";\r
-  }\r
-  :local mailStep3Subject $mailSubjectPrefix;\r
-  :local mailStep3Body  "";\r
-  :if ($targetOsVersion = $runningVersion) do={\r
-    :log info "$SMP Successfully verified new RouterOS version: target: `$targetOsVersion`, current: `$runningVersion`";\r
-    :set mailStep3Subject ($mailStep3Subject . " - Update completed - Backup created");\r
-    :set mailStep3Body ($mailStep3Body . "RouterOS and routerboard upgrade process was completed");\r
-    :set mailStep3Body ($mailStep3Body . "\nNew RouterOS version: v.$targetOsVersion, routerboard firmware: v.$deviceRbCurrentFw");\r
-    :set mailStep3Body ($mailStep3Body . "\n$changelogUrl\nBackups of the upgraded system are in the attachment of this email.\n\n$mailBodyDeviceInfo\n\n$mailBodyCopyright");\r
-    :set mailAttachments [$FuncCreateBackups $backupNameAfterUpdate $BackupPassword $BackupSens];\r
-  } else={\r
-    :log error "$SMP Failed to verify new RouterOS version: target: `$targetOsVersion`, current: `$runningVersion`";\r
-    :set mailStep3Subject ($mailStep3Subject . " - Update failed");\r
-    :set mailStep3Body ($mailStep3Body . "The script was unable to verify that the new RouterOS version was installed, target version: `$targetOsVersion`, current version: `$runningVersion`\nCheck device logs for more details.\n\n$mailBodyDeviceInfo\n\n$mailBodyCopyright");\r
-  }\r
-  $FuncSendEmailSafe $EmailGeneralTo $mailStep3Subject $mailStep3Body $mailAttachments;\r
-  :if ([:len $mailAttachments] > 0) do={\r
-    :log info "$SMP Cleaning up backup files from the file system...";\r
-    /file remove $mailAttachments;\r
-    :delay 2;\r
-  }\r
-  :log info ("$SMP Final report email sent successfully, and the script has finished.");\r
-}\r
-:log info ("$SMP the script has finished, script step: `$scriptStep` \n\n");\r
-\r
-} do={:global ExitError; $ExitError $ExitOK [ :jobname ] $Err}\r
+#!rsc by Vados
+# RouterOS script: AM-Fetch-Generator
+# Script comment: Downloader for Amnezia generated scripts
+# Copyright (c) 2007-2026 Vados <vados@vados.ru>
+#
+#
+# requires RouterOS, version>=6.43.7
+# requires device-mode, fetch
+#
+# Updated: 17/08/2026
+# Website: https://github.com/vados-dev/
+#:local ExitOK false;
+#:onerror Err {
+#  :global GlobalConfReady; :global GlobalFuncReady;
+#  :retry { :if ($GlobalConfReady != true || $GlobalFuncReady != true) \
+#      do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;
+#  :local ScriptName [ :jobname ];
+# ============================================================
+# AWG Proxy -- MikroTik RouterOS (protocol: v2)
+# 2026-07-21 10:33:39
+# ============================================================
+
+# 0. Check prerequisites
+:if ([:len [/system/package/find where name="container" disabled=no]] = 0) do={
+  :put "Container package is not installed or disabled. Install it and reboot."
+  :error "Usage: /system/device-mode/update container=yes"
+}
+
+# Check storage device
+{
+  :local targetDisk "usb1"
+  :local diskFree 0
+  :do { :set diskFree [/disk/get [find where mount-point=$targetDisk] free] } on-error={}
+  :if ($diskFree = 0) do={
+    :local baseDisk $targetDisk
+    :local dashPos [:find $targetDisk "-part"]
+    :if ([:typeof $dashPos] != "nil") do={ :set baseDisk [:pick $targetDisk 0 $dashPos] }
+    :if ([:len [/disk/find where slot=$baseDisk]] > 0) do={
+      :put ("Device $baseDisk found but $targetDisk is not available.")
+      :put "Format $baseDisk as ext4? ALL DATA WILL BE ERASED!"
+      :put "Press 'y' to confirm, any other key to cancel:"
+      :local key [/terminal/inkey timeout=30]
+      :if ($key = 121 || $key = 89) do={
+        :put "Formatting $baseDisk as ext4..."
+        /disk/format-drive $baseDisk file-system=ext4 label=$baseDisk
+        :delay 3s
+        :do { :set diskFree [/disk/get [find where mount-point=$targetDisk] free] } on-error={}
+        :if ($diskFree = 0) do={
+          :put ("ERROR: $targetDisk not found after formatting.")
+          :put "Check mount point: /disk/print"
+          :error ("Mount point $targetDisk not found after formatting")
+        }
+        :put ("Formatted OK. Free: " . ($diskFree / 1048576) . " MB")
+      } else={
+        :error "Formatting cancelled"
+      }
+    } else={
+      :put ("ERROR: Storage device $targetDisk not found.")
+      :put "Check available disks: /disk/print"
+      :error ("Storage not found: " . $targetDisk)
+    }
+  } else={
+    :put ("Storage OK: $targetDisk (" . ($diskFree / 1048576) . " MB free)")
+  }
+}
+
+# 1. Uninstall script
+/system/script/add name=awg2vds-uninstall comment=awg2vds source={
+  :put "Uninstallimg AmneziaWG..."
+  :log info "Uninstallimg AmneziaWG..."
+  :local prevDNS ""
+  :do { :set prevDNS [/container/envs/get [find where list="awg2vds-env" key="AWG_PREV_DNS"] value] } on-error={}
+  :local prevTmpdir ""
+  :do { :set prevTmpdir [/container/envs/get [find where list="awg2vds-env" key="AWG_PREV_TMPDIR"] value] } on-error={}
+  /ip/route/remove [find where comment=awg2vds-tunnel]
+  /ip/route/remove [find where comment=awg2vds-dns]
+  /container/stop [find where interface=veth-awg2vds]
+  :delay 7s
+  /container/remove [find where interface=veth-awg2vds]
+  /container/envs/remove [find where list="awg2vds-env"]
+  :if ($prevDNS != "") do={
+    :do { /ip/dns/set servers="$prevDNS" } on-error={}
+    :put ("DNS restored to: $prevDNS")
+  }
+  /container/config set tmpdir=$prevTmpdir
+  :put ("Container tmpdir restored to: $prevTmpdir")
+  /ip/firewall/nat/remove [find where out-interface="wg-awg2vds"]
+  /ip/firewall/nat/remove [find where src-address="172.20.200.68/30"]
+  /ip/address/remove [find where address="172.20.200.69/30"]
+  /interface/veth/remove [find where name="veth-awg2vds"]
+  /interface/wireguard/peers/remove [find where interface="wg-awg2vds"]
+  /ip/address/remove [find where interface="wg-awg2vds"]
+  /interface/wireguard/remove [find where name="wg-awg2vds"]
+  :do { /file/remove [find where name~"awg2vds.+tar"] } on-error={}
+  :do { /file/remove [find where name="usb1/awg2vds"] } on-error={}
+  :do { /file/remove [find where name="usb1/ru_ranges_timeout.rsc"] } on-error={}
+  :do { /file/remove [find where name~"usb1/pull"] } on-error={}
+  :put "Uninstall AmneziaWG Proxy complete!"
+  :log info "Uninstall AmneziaWG Proxy complete!"
+  /system/script/remove [find where name=awg2vds-uninstall]
+}
+
+# 2. Network infrastructure
+/interface/veth/add name=veth-awg2vds address=172.20.200.70/30 gateway=172.20.200.69
+/ip/address/add address=172.20.200.69/30 interface=veth-awg2vds
+/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.20.200.68/30
+
+# 3. WireGuard interface (MikroTik derives the public key automatically)
+/interface/wireguard/add name=wg-awg2vds private-key="4LNSJJNEDeT2LFXkFx0XyrNp2Mp7YXlS8SawhqNfKGQ=" listen-port=26084 disabled=yes
+/interface/wireguard/peers/add interface=wg-awg2vds public-key="qHFd72XDJJ5UrUZCZ0vRFQmzxP7eUYcOuaGL9ZbHtyg=" preshared-key="ckhzjCcr15ve+IeDRYveYITR7a/CMZCcOZ2Z0cABKD8=" endpoint-address=172.20.200.70 endpoint-port=51820 allowed-address=10.10.10.1/24,10.30.30.0/24,0.0.0.0/0 persistent-keepalive=10
+/ip/address/add address=10.10.10.2/24 interface=wg-awg2vds
+
+# 4. Container environment variables
+/container/envs/add list=awg2vds-env key=AWG_LISTEN value=":51820"
+/container/envs/add list=awg2vds-env key=AWG_REMOTE value="109.107.177.79:443"
+/container/envs/add list=awg2vds-env key=AWG_JC value="6"
+/container/envs/add list=awg2vds-env key=AWG_JMIN value="171"
+/container/envs/add list=awg2vds-env key=AWG_JMAX value="481"
+/container/envs/add list=awg2vds-env key=AWG_S1 value="50"
+/container/envs/add list=awg2vds-env key=AWG_S2 value="139"
+/container/envs/add list=awg2vds-env key=AWG_H1 value="1189447486-1189448396"
+/container/envs/add list=awg2vds-env key=AWG_H2 value="538303610-538304276"
+/container/envs/add list=awg2vds-env key=AWG_H3 value="101001960-101002598"
+/container/envs/add list=awg2vds-env key=AWG_H4 value="1783887443-1783887851"
+/container/envs/add list=awg2vds-env key=AWG_SERVER_PUB value="qHFd72XDJJ5UrUZCZ0vRFQmzxP7eUYcOuaGL9ZbHtyg="
+/container/envs/add list=awg2vds-env key=AWG_CLIENT_PUB value=[/interface/wireguard/get [find name=wg-awg2vds] public-key]
+/container/envs/add list=awg2vds-env key=AWG_S3 value="17"
+/container/envs/add list=awg2vds-env key=AWG_S4 value="6"
+/container/envs/add list=awg2vds-env key=AWG_I1 value="<b 0x000100182112a442><r 12><b 0x80220009706a70726f6a65637400000080280004><r 4>"
+/container/envs/add list=awg2vds-env key=AWG_I2 value="<r 32><t>"
+/container/envs/add list=awg2vds-env key=AWG_I3 value="<rd 16><r 24>"
+/container/envs/add list=awg2vds-env key=AWG_I4 value="<t><rc 20>"
+/container/envs/add list=awg2vds-env key=AWG_I5 value="<r 18>"
+
+# 5. DNS
+{ :local rawDNS [/ip/dns/get servers]; :local prevDNS ""; :foreach s in=[:toarray $rawDNS] do={ :if ([:len $prevDNS] > 0) do={ :set prevDNS "$prevDNS,$s" } else={ :set prevDNS $s } }; /container/envs/add list=awg2vds-env key=AWG_PREV_DNS value="$prevDNS" }
+# NOTE: replaces existing DNS configuration
+/ip/dns/set servers=10.10.10.1
+/ip/route/add dst-address=10.10.10.1/32 gateway=wg-awg2vds distance=1 comment=awg2vds-dns
+
+# 6. Download, create and start container
+:local prevTmpdir [/container/config/get tmpdir]
+/container/envs/add list=awg2vds-env key=AWG_PREV_TMPDIR value=$prevTmpdir
+/container/config set tmpdir=usb1/pull memory-high=200M
+{
+  :local arch [/system/resource/get architecture-name]
+  :local ver [/system/resource/get version]
+  :local dotPos [:find $ver "."]
+  :local rest [:pick $ver ($dotPos + 1) [:len $ver]]
+  :local endPos [:find $rest "."]
+  :if ([:typeof $endPos] = "nil") do={ :set endPos [:find $rest " "] }
+  :local minor [:tonum [:pick $rest 0 $endPos]]
+  :local suffix ""
+  :if ($minor <= 20) do={ :set suffix "-7.20-Docker" }
+  :local file ""
+  :if ($arch = "arm64") do={ :set file ("awg-proxy-arm64" . $suffix . ".tar.gz") }
+  :if ($arch = "arm") do={ :set file ("awg-proxy-arm" . $suffix . ".tar.gz") }
+  :if ($arch ~ "x86") do={ :set file ("awg-proxy-amd64" . $suffix . ".tar.gz") }
+  :if ($file = "") do={ :error "Unsupported architecture: $arch" }
+  #:local url "https://github.com/timbrs/amneziawg-mikrotik-c/releases/latest/download/$file"
+  :local url "https://ros.vados.ru/amneziawg/img/$file"
+  :local filePath ("usb1/pull/" . $file)
+  :do { /file/make-directory usb1/pull } on-error={}
+  :if ([:len [/file/find where name=$filePath]] = 0) do={
+    :local freeStorage 0
+    :do { :set freeStorage [/disk/get [find where mount-point="usb1"] free] } on-error={}
+    :if ($freeStorage < 262144) do={
+      :put ("WARNING: Low disk space (" . ($freeStorage / 1024) . "KB free). Need at least 256KB.")
+      :put "See: https://github.com/timbrs/amneziawg-mikrotik-c#insufficient-disk-space"
+      :error "Insufficient disk space"
+    }
+    :put ("Fetching: $url -> " . $filePath)
+    /tool/fetch url=$url dst-path=$filePath http-max-redirect-count=10
+  } else={
+    :put ("File already exists: " . $filePath)
+  }
+  /container/add file=$filePath interface=veth-awg2vds envlist=awg2vds-env hostname=awg2vds root-dir=usb1/awg2vds logging=no start-on-boot=yes comment=awg2vds
+  :if ($minor > 20) do={ [:parse "/container/set [find where interface=veth-awg2vds] shm-size=4M"] }
+  /file/remove $filePath
+  :local freeMem [/system/resource/get free-memory]
+  :if ($freeMem < 16777216) do={
+    :put ("WARNING: Low memory (" . ($freeMem / 1048576) . "MB free). 16MB+ recommended.")
+  }
+  /container/start [find where interface=veth-awg2vds]
+  :do { /file/remove [find where name="console-dump.txt"] } on-error={}
+  :put "Waiting for container to start..."
+  :delay 5s
+  /interface/wireguard/enable wg-awg2vds
+  :put "WireGuard interface enabled"
+  :put "Installation complete!"
+  :put "Ping test: 10.10.10.1 via AmneziaWG tunnel. repeat 10 times"
+  /ping 10.10.10.1 count=10 interval=1
+  :put ""
+  :put "======= NEXT STEPS ======="
+  :put ""
+  :put "Route specific traffic through the AmneziaWG tunnel:"
+  :put ""
+  :put "  Route a single host:"
+  :put "    /ip/route/add dst-address=8.8.8.8/32 gateway=wg-awg2vds comment=awg2vds-tunnel"
+  :put ""
+  :put "  Route a subnet:"
+  :put "    /ip/route/add dst-address=100.0.0.0/8 gateway=wg-awg2vds comment=awg2vds-tunnel"
+  :put ""
+  :put "  Remove a route:"
+  :put "    /ip/route/remove [find where comment=awg2vds-tunnel dst-address=8.8.8.8/32]"
+  :put ""
+  :put "  Show all tunnel routes:"
+  :put "    /ip/route/print where comment=awg2vds-tunnel"
+  :put ""
+  :put "  Uninstall:"
+  :put "    /system/script/run awg2vds-uninstall"
+  :put "========================="
+}
+
+# 7. Verification
+# /container/print
+# /interface/wireguard/print
+# /interface/wireguard/peers/print
index 127205b021c0a42dbf5816296dc39c4413f968d9..8f4876c9e23b022bf1ce86cfb7f06edd6223efe9 100644 (file)
@@ -17,9 +17,9 @@
 :global GlobalFuncReady false;
 
 # Git commit id & info, expected configuration version
-:global CommitId "main/9348/4b652655";
+:global CommitId "main/9349/97bb2cdb";
 :global CommitTAG "unknown";
-:global CommitInfo "Autocommit in repo: ros.vados.ru, generated by owner: root, in 21:10:04 17.08.2026.";
+:global CommitInfo "Autocommit in repo: ros.vados.ru, generated by owner: root, in 21:15:04 17.08.2026.";
 
 # The variables are received right here.
 :global GlobalConfVersion 140;