mirror of
https://github.com/bivlked/amneziawg-installer.git
synced 2026-10-14 19:45:02 +00:00
26 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1f0d54aca5
|
docs: cascade, WARP, contributor and release docs after v6.0.0 (#355) | ||
|
|
c705ba1bdf
|
docs: client table snapshot of 12 October 2026 (#348)
A fresh snapshot of the client table, so the release is not prepared on rows checked more than 30 days earlier. Every row of `docs/clients-matrix.json` was checked again on 12 October against the projects' release pages, the app stores and the code; the whole table now carries that one date. - Newer versions: WG Tunnel 5.8.1, WG Tunnel Desktop v2.4.0, AWG Manager v2.19.13, amneziawg-mikrotik-c v1.4.3. WG Tunnel moved to its core 1.9.x; the config parser there still reads the 3.1 keys. - awg-openwrt corrected: it was listed as third line only in the daily feed. The release packages for OpenWrt 25.12.5 and 24.10.8 were replaced on 22 September under the same tags and carry `kmod-amneziawg` 3.1.20260906 and `amneziawg-tools` 3.1.20260812. The row now says yes and warns that packages downloaded earlier and packages for older OpenWrt have no 3.1. - New rows: Throne (3.1 since 1.3.0, read in the wireguard-go build it pins; in 1.3.x some packets go out with less padding than set, fixed in 1.4.0-beta.1), the RomikB build of the AmneziaWG Windows client that the vendor docs point to for Windows 7 and 8 (v3.1.1, built on amneziawg-go v3.1.20260814), and official OpenWrt, which has no AmneziaWG package while openwrt/packages#30492 and openwrt/packages#30493 are open. - ADVANCED (RU and EN): the router answer is dated 12 October, names the new versions, adds awg-openwrt with the same caveat, and gives the `--protocol=2.0` advice only for firmware that speaks just the second line. The sing-box-extended note says it speaks 3.1 since v1.14.0-extended-2.7.0 and still crashes on our padding (shtorm-7/sing-box-extended#158 is open). The table intro says "3.1 since" also comes from the projects' code. - README (RU and EN): the client versions are dated 12 October. CHANGELOG (RU and EN): one sentence in the documentation item. |
||
|
|
6986b04564
|
docs: AmneziaWG 3.1 is the default for new installs (#338)
Documents the new default from #337 for the people who read the README and the guides, not the code. - README (RU and EN). The heading, subtitle, logo alt text and badge say AmneziaWG 3.1 / 2.0. The section about the third line becomes "AmneziaWG 3.1 by default": what the 3.1 profile adds, who needs `--protocol=2.0` before installing (routers on stock firmware, Hiddify, apps that are not updated), where the installer installs 2.0 by itself (kernel older than 6.7, ARM, tools or module without third-line support), and that a running server keeps its generation. Quick Start gets a one-line pointer to `--protocol=2.0`. The client lists and FAQ answers name the versions that understand 3.1. - ADVANCED (RU and EN). Two new subsections: "The 3.1 profile: what the installer turns on and what it leaves out" (HeaderProtectionKey per install, ContentPaddingAddition 32-128, H1-H4 = 1-4, S3/S4 from 12, no RandomTrailers, DisableCookies or timers) and "Where 2.0 is installed instead of 3.1" (the two checks, the reason codes, the init keys, the cost of changing the generation). The module-line table gets a "profile without --protocol" column; the client compatibility tables are rebuilt with a 3.1 column and versions as of 5 October 2026; FAQ answers about the yellow mark, changing parameters on 3.1, where the key lives and router support are updated; `--protocol` in the CLI reference matches `--help`. New explicit anchors `awg3-fallback-adv` and `client-gen-adv`, present in both languages. - INSTALL_VPS (EN and RU). A paragraph about the protocol generation next to the install command, and the update section says that updating keeps the generation. - Way back from 3.1 to 2.0. README and INSTALL_VPS (RU and EN) say it the same way as the move up: `--uninstall`, then an install with `--protocol=2.0` and new profiles for every client. - Tables built from data files (ADVANCED, RU and EN). The client table is rendered by `scripts/update-client-tables.sh` from `docs/clients-matrix.json`, where every row carries a basis (the project's pages, its code or a test on a 3.1 profile), the evidence that basis requires, and a check date. A second table, in "Where 2.0 is installed instead of 3.1", shows which generation a new install gets on each system: its cells are the answers of the installer's own step 0 check, cut out of both installers and run on each system's stock kernel (new `stock_kernel` field in `docs/support-matrix.json`) for x86_64 and ARM. The footnote's claims about ARM and the step 3 reason codes are checked against the installer's behaviour. Check 15b in `check-docs-consistency.sh` fails when a table drifts from its data, and when a client row is more than 30 days older than the release date of the current version (taken from the CHANGELOG heading, not from a clock). - PPA module updates (ADVANCED, RU and EN). A paragraph on how the module from the PPA changes (with `apt upgrade` and when the installer runs again), why apt cannot roll it back, how to hold a build and what releases the hold, and how to see the running build (`srcversion`). - CHANGELOG. The Unreleased entry for the new default, starting with "what changes for you", plus a documentation bullet for the points above. - Facts block guard. `scripts/update-facts-block.sh` did not see single-quoted `printf` writes, so after #337 the README still promised "generated configs stay 2.0" and CI stayed green. The guard now requires the 3.1 profile lines to be written and called from both renderers, `PROTOCOL_DEFAULT="3.1"` to be assigned once and used, the `--protocol` flag and the fallback to exist, and still rejects third-line parameters the profile does not set, in any echo, printf or sed form. Each bypass has a test case that fails on the previous guard. - Installer final report. The 3.1 note links straight to the client generation table (`ADVANCED.md#client-gen-adv`, `ADVANCED.en.md#client-gen-adv` in the English installer). |
||
|
|
9e4685839e
|
chore: drop Ubuntu 25.10 from supported systems (#343)
Canonical ended support for Ubuntu 25.10 on 2026-07-01, and no security updates are published for it. This takes it off the list of systems the installer supports. - `check_os_version` no longer lists 25.10, and the help line reads Ubuntu 24.04 / 26.04, Debian 12 / 13. On 25.10 the installer does what it does on any version outside the list: it warns about an untested release and asks for confirmation; `--yes` carries on. A second warning line names the releases to pick for a server. - The ARM prebuilt for 25.10 (`ubuntu-2510-arm64`) is no longer built, and the installer no longer maps 25.10 to it. Packages built earlier stay in the `arm-packages` release. ARM hosts on 25.10 build the module through DKMS. - A host that already carries a prebuilt module package for the running kernel no longer slides into a DKMS build next to it when no prebuilt can be installed (the case for every ARM host on 25.10 after this change, or a supported target during a download failure). That would leave two module trees, so step 2 stops and says what to do: rerun later after a network failure, or purge the old package when no prebuilt exists for the kernel any more. A package left from an earlier kernel does not stop it, so rerunning the installer after a kernel update on ARM works as before. - `docs/support-matrix.json` loses the 25.10 entry; README, INSTALL_VPS, CASCADE, ADVANCED, ROADMAP (RU and EN), CONTRIBUTING and the issue, discussion and PR templates follow. The compatibility table keeps a 25.10 row marked as not supported, with the way off it (`do-release-upgrade` to 26.04, then the latest installer again). - Debian 12 stays: its regular support ended, but Debian LTS patches it until 2028-06-30. New tests tie the installer and the ARM build to the support matrix in both directions (the families and versions `check_os_version` accepts, the prebuilt targets in `arm-build.yml`), run `check_os_version` for every matrix platform and for neighbouring releases outside the matrix, and cover the new prebuilt check, including a package for an earlier kernel, an unreadable file list and a Raspberry Pi kernel name. |
||
|
|
f89a14d38f
|
installer: new installs default to AmneziaWG 3.1 and fall back to 2.0 where 3.1 cannot run (#337)
A new install without --protocol now gets AmneziaWG 3.1. On a machine where 3.1 cannot run and the generation was not chosen, the installer installs 2.0 by itself and says why in a block that is the same interactively and under --yes. An explicit --protocol=3.1 on such a machine still stops with the reason code. --protocol=2.0 keeps installing 2.0. Existing installs keep their generation: a server without a generation marker reads as 2.0, as before. 3.1 gives way to 2.0 at step 0 for the architecture (ARM, anything that is not x86_64) and the kernel (older than 6.7, Debian 12), and at step 3 for the installed tools and the loaded module. At step 3 the installer generates one 2.0 parameter set with the saved Jc/Jmin/Jmax and preset (--jc=0, --preset=mobile and --no-cps carry over), applies exactly that set to a temporary interface, reads it back, and only then rewrites the settings file. If the module refuses the set, the install stops with the settings file untouched. A 2.0 set saved by the step 0 fallback is probed the same way at step 3, before any key is made. An install that has reached step 6 (server keys, configs, profiles or a live awg0) is never downgraded, checked at step 0 of the same run and again right before the fallback. Step 6 hands out 3.1 profiles only after the step 3 check passed in the same run, and never falls back. An existing 3.1 server that no longer passes the check is told the reason and a repair that leaves it alone; removal is named only as the last resort, and a failure of the check itself is reported as an installer error, not as a reason to remove anything. The settings file gets two new keys, AWG_PROTOCOL_SOURCE (default or explicit) and AWG_PROTOCOL_FALLBACK (the reason code). The settings writer moved into its own function unchanged, so step 0 and step 3 share it. A short notice before step 1 says the default is 3.1 and who should rerun with --protocol=2.0; the final report names the generation, the fallback reason if any, and the clients 3.1 needs; --help describes the default and the fallback. The README DeepWiki badge is served from docs/badges/deepwiki.svg, since deepwiki.com/badge.svg answers automated clients with a 429 and the GitHub image proxy showed a broken image. |
||
|
|
9f8c717efc
|
docs: audit 2026-09, part 3 (low findings) and a wider docs guard (#314)
* docs: README test count, guest command, formal address, PPA codename check, threat model link Audit 2026-09 low findings K-25, U-02, U-05, T-08 (README part) and the PPA codename rows: the installer checks whether the PPA has packages for the release codename and switches to noble only if it does not (install_amneziawg.sh, codename probe); checked live: resolute answers, questing does not. * docs: install guides link targets, flag list, PPA codename check Audit 2026-09 low findings C-09 (client management link goes to the management section), C-10 (the two QR codes link to the vpn:// section), U-04 (the long English paragraph becomes a flag list) and the PPA wording in both guides: the installer switches to noble only when the PPA has no packages for the release codename. * docs: ADVANCED low findings, FAQ anchors, stats and diagnostic samples from code Audit 2026-09 low findings C-11, C-12, C-13, K-13, K-14, K-15, K-16, K-17, K-18, K-19, K-20, K-21, K-22, K-23, K-24, K-26 and G-06. The stats sample is rendered with the real format_bytes and printf formats of both manage scripts in a UTF-8 locale; the diagnostic table lists the 17 sections in code order. T-Mobile is the Russian carrier (Moscow and region, per discussion #45), the tmobile_us profile name is historical. Five FAQ questions get their own anchors, identical in RU and EN (add only), and six inbound links now point at the specific question. * docs: cascade and WARP low findings, wgcf checksum check Audit 2026-09 low findings C-08, C-15, C-16, K-31, K-32, T-10, U-09. The client samples show what the installer issues (two DNS servers, 0.0.0.0/0 plus ::/0, which the full-tunnel generator always appends); the WARP step downloads wgcf under its release name, checks it against checksums.txt of the same release and only then renames it, checked in a throwaway container with a good and a tampered download; the security section says what that check does not cover. * docs: signing README, support matrix, contributing and security scope Audit 2026-09 low findings C-17 (signing/README uses scripts/sign-release.sh and verifies with the whole key via -P, from a release and from a git checkout), K-27 (Ubuntu 26.04 uses resolute from the PPA and noble only if it is missing: support matrix, CONTRIBUTING, PR template; last_verified is not advanced because only this field was rechecked), T-08 (SECURITY scope names both languages and the release pipeline, links the README section), U-07 (CONTRIBUTING lists all RU/EN pairs, qrencode and jq, and the [Unreleased] rule). * fix(en): outdated-library warning in manage no longer cut off Audit 2026-09 K-33: the section name sat in bare double quotes inside a double-quoted log_warn argument, so the shell split it into four words and log_msg printed the message cut off at (section How. The name now uses single quotes. New test evaluates the exact line from both scripts with a counting log_warn stub: the English one failed with argc=4 before the fix, the Russian one already passed. * ci(docs): guard cross-file and HTML anchor links, RU/EN anchor sets, split-mode wording Audit 2026-09 question 16. New check 16 resolves ](file.md#x) and href="...#x" links, relative to the linking file and with percent-encoded fragments decoded (check 1 only saw ](#x) inside one file); it also fails when it finds no links at all. Check 17 compares the explicit anchor sets of the ADVANCED, CASCADE and WARP-RU pairs. Check 18 keeps the two links that resolved but pointed at the wrong section (C-09, C-10) from coming back. Check 7b also catches the C-05 wording (split modes (2/3)) without flagging the legitimate split mode of --route-custom, and uses a locale-independent pattern: a Cyrillic range made grep exit 2 in the C locale, which an if reads as no match. Check 8 also scans the Q&A discussion template. Every new check is shown failing on its defect in a throwaway repository. * docs: changelog for documentation audit part 3 * docs: review fixes for part 3 The WARP step removes a wgcf left from an earlier run and runs the new one only after the checksum check in the same && chain: checked in a container, the previous recipe ran the stale binary twice after a tampered download, the new one runs nothing. The checksum note says it catches a broken or wrong download, not a compromise of the release page. The PPA wording follows the code: the installer requests dists/<codename>/Release and switches to noble when there is no answer, including when the PPA is unreachable; no statement about what the PPA publishes. The ARM hint names the DKMS fallback log line; the stats sample keeps config order; the WARP IPv6 note gives version ranges and the regen condition; signing/README says where the key trust comes from; the remaining informal address in README is gone; CHANGELOG RU/EN aligned. * ci(docs): guard fails loudly on what it cannot see Review fixes for checks 8, 16-18 and the slug generator. grep without PCRE stops the script instead of letting checks 1, 16 and 17 find nothing. Check 16 rejects link forms its parser cannot see (reference-style, single-quoted or spaced href, uppercase HREF, .MD) instead of skipping them, and treats URL schemes case-insensitively. Check 17 fails on an empty anchor set or a failed diff. Check 18 is keyed on the link target, not the link text, and fails on a missing file, as does check 8. Check 7b turns a grep error into a failure. The slug generator keeps the leading hyphen GitHub keeps for headings that start with an emoji; the old test expected the trimmed form, which accepted a broken link. New tests cover every mutation from the review: seven mutants, each fails exactly one test, the unmutated copy fails none. * ci(docs): guard closes the remaining silent paths from review Check 7b fails on a missing file; check 16 fails when a file cannot be read or the form grep errors, rejects two more non-canonical forms (space after the parenthesis, unquoted href) and leaves external URLs alone in every form; check 18 finds the wrong target in any wrapper (](...), ](./...), href) outside code blocks. New tests: grep without -P, 7b missing file and grep error, trailing slug hyphen, the new forms and external URLs that must not fail. Eight mutants, each adds a failing test. * ci(docs): guard closes the last review findings Check 18 finds the wrong target with a title, a leading slash, angle brackets or percent-encoding. Code blocks: a closing fence indented up to three spaces ends the block, and an unclosed block fails instead of hiding the rest of the file. Check 16 no longer takes ?href= inside an external URL or <https://...> in a reference definition for a local link. Every new branch is covered by a test and by a mutant that makes it fail. * ci(docs): href at line start and a path named in prose An href that starts a line inside a multi-line tag is checked again; a path named in prose is no longer taken for the misrouted link. * ci(docs): check 18 also sees a link target that starts its own line A Markdown link whose destination sits on the next line is still the misrouted link. The two remaining line-start href forms get their own tests. |
||
|
|
ad7b43f214
|
docs: audit 2026-09 part 2 (verified updates, uninstall, cascade removal, guide parity) (#313)
Documentation audit 2026-09, part 2: verified script updates that refuse rollback and mixed releases, what the installer changes and what uninstall leaves, cascade removal tested in a network namespace, install guide parity, review fixes and CHANGELOG entries. |
||
|
|
6749578121
|
docs: audit 2026-09 part 1 (first screen, QR, installer questions, reissue flags, signing key, FAQ) (#312)
* docs: first-screen, QR, installer questions, reissue flags, signing key Documentation audit 2026-09, high findings and approved texts. - README first screen: the installer creates my_phone and my_laptop and saves their files in /root/awg/ instead of printing a QR code; UFW is offered, not guaranteed. New Russian subtitle and a link to the English README. - The Amnezia VPN app scans name.vpnuri.png; name.png is the QR of the .conf (README RU/EN, INSTALL_VPS.md). - The package cleanup question and "Enable UFW? [y/N]" are described; Enter leaves the firewall off (README RU/EN, INSTALL_VPS RU/EN). - Flags that force reissuing configs now include --mobile and --port; the mobile advice no longer says to just reinstall a running server with --mobile. - ARM with a prebuilt module has no DKMS: after a kernel change run the installer again. - Signature check with minisign -P and the whole public key; 3E598A1C01907E17 is the key ID, not a fingerprint (README, SECURITY, SIGNING_DESIGN); what the signature covers and what it does not. - Five new README FAQ questions; the routing note in .devin/wiki.json. - CHANGELOG RU/EN. * docs: review follow-up for the audit high findings - The SHA256 coverage of the downloaded scripts holds only while AWG_BRANCH is left at its default (README RU/EN). - name.png is the QR of the .conf for AmneziaWG clients; a plain WireGuard client cannot import it (INSTALL_VPS EN/RU, including an older RU line). - KEYS.txt is in every signed release (v5.29.0 and later), not every release. - The UFW question comes only when UFW is not on yet. - SIGNING_DESIGN step 2: keep a copy of the key, which step 4 passes whole. - Wording fixes in INSTALL_VPS.md and the CHANGELOG entry about the subtitle. * docs: name.png is for AmneziaWG clients everywhere Review follow-up. ADVANCED still said WireGuard-compatible clients (including wireguard-apple and wg-quick) scan name.png, and INSTALL_VPS named Linux wg-quick for the .conf, while a plain WireGuard client cannot import AmneziaWG parameters. Both now say AmneziaWG clients and awg-quick (RU and EN). * docs: awg-quick takes the .conf as a file, it does not scan the QR Review follow-up: the ADVANCED line listed awg-quick among the apps that scan name.png. It now says AmneziaWG apps import it by QR and awg-quick takes the same .conf as a file (RU and EN). The header of test_qr_vpnuri.bats no longer calls name.png a QR for WireGuard-compatible clients. * docs: name.png is for AmneziaWG clients with QR import Review follow-up: AmneziaWG for Windows imports the .conf as a file, like awg-quick, so it is no longer given as an example of QR import (ADVANCED RU/EN, test header). * docs: --endpoint also forces reissuing configs Review follow-up: --force --endpoint changes AWG_ENDPOINT while step 6 keeps existing peers and their client files, so their profiles keep the old Endpoint until regen. Added to the reissue lists in README and both install guides, and to the CHANGELOG entry. * docs: --endpoint changes only reissued configs, old ones keep working Review follow-up: Endpoint lives only in the client config, so --endpoint does not break old configs by itself; they keep the previous address and work while it still reaches the server, and get the new one after regen. Separated from the flags that do break them (README, both install guides, CHANGELOG). |
||
|
|
a95c8b1e32
|
feat(install): the default routing mode is the full tunnel (v5.34.0) (#273)
* feat(install): the default routing mode is the full tunnel A fresh install now hands clients `AllowedIPs = 0.0.0.0/0, ::/0` instead of the 34-subnet list. The list mode is not removed: it stays as menu entry 2 and as `--route-amnezia`. Existing servers keep the mode recorded in their settings. Why. The Amnezia app opens its own split-tunneling page only when it sees `0.0.0.0/0` among the client routes, and the form it reliably recognises is the pair `0.0.0.0/0, ::/0`; handed a subnet list it concludes that the server already splits the traffic, says so, and hides its own toggle. On Linux, awg-quick engages its fwmark machinery only for a `/0` route, which a list-shaped IPv4 config does not carry - on the bench that produces a routing loop. The Amnezia app's own server template emits `0.0.0.0/0, ::/0` as well. The cost is stated in the docs rather than hidden: the LAN goes into the tunnel along with everything else, and whether it stays reachable is decided by the client. Whoever needs it out of the tunnel installs with `--route-amnezia`. Fixed along the way: - the network prompt of mode 3 could spin forever on end of input or with the terminal gone: the read exit status is now checked and the retries bounded - a reinstall assigned the install default over the mode saved in the config - `ALLOWED_IPS_MODE` from the config was never validated, and a garbage value was treated as a custom list further down - a mode change without an explicit flag printed no re-issue hint - an unrecognised answer in the menu fell back to the default silently Release v5.34.0. * docs(advanced): hyphen-minus on the two lines this branch already touched The dash policy exempts legacy documents from a mass purge, but the CI check counts a modified line as an added one, so the two lines edited earlier on this branch had to carry their own punctuation. Only those two lines are touched, and only their dashes. * test(routing): cover dual-stack on the new default and tighten the extraction guards The dual-stack branch was only ever driven through the list-shaped mode, which a default install no longer produces. The isolation test read one language variant and guarded its extraction with a bare -n, which the first of the two extracted functions satisfies on its own - a rename of the second would have failed on the value instead of naming the cause. * chore(release): sign v5.34.0 |
||
|
|
013d3c012e
|
release: v5.30.0 (#248)
Install and update commands move to releases/latest/download, so a copied line no longer goes stale with the next release and serves a signed asset. Four pins stay on purpose and the docs guard now explains which and why. A guard against oversized I1-I5, which make the interface dump loop forever upstream. Adding it exposed the same mistake in four neighbouring places: the guard sets a flag and the code after it kept building positive claims from the empty string left behind. diagnose said "I1=absent" at the moment the guard fired because I1 was oversized, and with a carrier profile turned that into a green tick; list, given a timeout in this same branch but no failure handling, turned a visible hang into a complete and entirely wrong table. All eighteen interface calls across the four scripts are bounded now, timeouts are named separately from other failures, and the honest states survive. The size parser no longer returns zero with a success status for input it did not parse, since zero means "no masking packets" and switches the protection off. ADVANCED gains a client generation matrix answering which generation a client speaks, with the weaker rows marked as inferences. Nine claims that did not match the code or the world were corrected. |
||
|
|
fea8e74bab
|
docs: a dated facts block in both READMEs, generated from repository data (#241)
The block sits at the top of README.md and README.en.md and carries a date, so it promises the reader that the numbers are fresh. A hand-written block breaks that promise silently: it starts lying the day someone forgets to update it, and the date next to it makes it look more trustworthy than ordinary prose. So every value is derived instead of typed: installer version and release date -> SCRIPT_VERSION + the CHANGELOG heading the OS lists -> docs/support-matrix.json project_policy the date the OS data was verified -> verification.last_verified architectures -> the arch: fields in arm-build.yml The one claim that cannot be derived is the config profile, so it is tied to the code instead: if a third-line parameter reaches a config template, the generator stops rather than quietly emitting a promise that configs are still 2.0. The date comes from the repository, never from the clock. A generated block stamped with today would turn the check red the day after every commit, and a check that fails by default is read as broken and then ignored. check-docs-consistency.sh verifies the stored block against the generator, so this runs in CI and in preflight, and docs/RELEASE_PROCESS.md gains the regeneration step, which is now on the release path: bumping the version changes what the block must say. Four defects were found by review after the first version, all the same shape, a guard reporting success having checked nothing: - The check trusted the generator's exit code alone, so an empty file in place of the generator produced PASS. Worse, dropping the --check token made the checker run in write mode: it rewrote the working tree in CI, printed PASS and destroyed the evidence. Writing is now explicit (--write), a call with no argument refuses and exits 2, and the check additionally requires the success signature in the output. - Write mode could have destroyed both READMEs and stayed green, because the check and the tests only ever looked at the text between the markers. The generator now verifies the rest of the file itself before writing, writes atomically through a temp file as the project convention requires, and a test compares a hash of everything outside the block across the write. - The third-line parameter guard knew one of the two ways a parameter reaches a config, and five of the nine names ADVANCED.md documents, so it protected its own claim more narrowly than the claim is stated. Optional parameters are written as echo "Name = ...", which is how I1-I5 are emitted and how HeaderProtectionKey would be added. - The write path validated and wrote one file at a time, so drift in README.md together with broken markers in README.en.md left the repository half updated, the state the surrounding comment claimed to prevent. Both files are now parsed, rendered and self-checked before either is replaced. The module row itself was wrong in both languages until someone read the installer: it credited the Amnezia PPA, which is false on kernels older than 6.7, a stock Debian 12 among them, where the installer deliberately declines the PPA module and builds a pinned 2.0 module from source. The block was stating the kind of untruth it exists to prevent. tests/test_facts_block.bats mutation-tests the guard in 28 cases: each case breaks exactly one link the check holds, including the inverse case where those parameter names appear legitimately and the guard must stay quiet. |
||
|
|
3fda0c9f92
|
release: v5.29.0 (#240)
* chore(release): prepare v5.29.0
Version bumped in all three kinds of place at once, because a partial bump is
rejected by preflight and, worse, ships an installer whose helper download
fails: 6 SCRIPT_VERSION/AWG_COMMON_VERSION assignments, 6 file headers with
their dates, 36 pinned raw-URL tags across the documentation, 2 README badges.
The four helper SHA pins were recomputed afterwards, against the working tree,
which is the correct source while the tag does not exist yet.
CHANGELOG.md and CHANGELOG.en.md gain the 5.29.0 section and its comparator
link; SECURITY.md moves the supported window to 5.29.x.
build-release-notes.sh now accepts a semver pre-release suffix and reads the
base version's changelog section. RELEASE_PROCESS.md prescribes rehearsing the
pipeline on a throwaway vX.Y.Z-rc1 tag, and release.yml passes the tag name
through verbatim, so the previous X.Y.Z-only check would have killed that
rehearsal at the notes step, before it reached the draft, the upload, the asset
count and the publish - everything the rehearsal exists to exercise. A
pre-release has no changelog section of its own and should not have one. Three
test cases cover it, two of which fail against the previous script.
update-sha-pins.sh prints the "no tag, comparing against the tree" notice once
per run rather than once per pin. The first attempt at this kept the flag
inside the function that produces the value, which runs inside a command
substitution, so the flag died with the subshell and the notice still appeared
four times; the flag now lives in the caller.
* feat(release): sign a release with one command instead of a manual loop
The trusted comment has to read exactly "amneziawg-installer <tag> <file>";
a typo there yields a signature that verifies cryptographically and is still
rejected by the release, which is found only after the tag is pushed. The
script composes it, validates the tag before asking for the password, asks
once for all six signings, and ends by running verify-signatures.sh so that
"signed 6" does not rest on minisign merely not crashing.
It refuses to run without a terminal. That is the regression it was written
for: the documented manual loop was run where stdin was not a terminal, its
read failed at once, the && chain skipped the signing, and the line finished
with no signatures written and nothing said. Six test cases cover the refusal
paths, because the happy path needs the private key and the happy path is not
where this went wrong.
* fix(release): find the signing key when HOME is not the Windows profile
bash launched from PowerShell or cmd reports HOME as /home/<user>, a path that
does not exist on disk, so a lookup anchored on HOME alone reported the key
missing while it sat in the Windows profile. USERPROFILE and HOMEDRIVE with
HOMEPATH are now tried as well.
The Windows to POSIX translation uses tr rather than ${x//\//}: measured on
bash 5 under Git Bash, that substitution returns the string untouched. The bug
would have been quiet, because MSYS happily opens the half converted path
C:\Users\biv/.minisign/..., so -f succeeds and the defect hides until an
environment that rejects such a path. cygpath is not used: a shell started from
PowerShell inherits the Windows PATH, where cygpath is usually absent, which is
precisely the environment the fallback exists for.
* fix(release): name the WSL trap instead of looking like a broken script
On Windows, `bash` typed in PowerShell or cmd is usually the WSL launcher at
C:\Windows\System32\bash.exe, not Git Bash. WSL inherits none of the
Windows environment: HOME points at a Linux home with no key in it, USERPROFILE
and HOMEDRIVE are empty, and MINISIGN_KEY exported on the same command line
never arrives either. Every fallback the script has was therefore invisible,
and the failure read as a defect in the script rather than as the wrong shell.
The key lookup now says so when it detects WSL, and RELEASE_PROCESS.md gives
the explicit Git Bash invocation. Verified by running the script under real
WSL, not by simulating one; a companion test guards the other direction, that
an ordinary shell is not told it is something it is not.
* chore(release): sign v5.29.0
* fix(docs): repair backspace bytes in the signing instructions, and guard the class
A doc edit assembled through a Python string containing System32\bash.exe wrote
a literal backspace (0x08) where the backslash-b was: the documented command was
unusable, and invisible - a terminal does not render the byte, grep over text
does not look for it, and the diff shows the line as correct. Python warned
about the neighbouring invalid escape and said nothing about this one, because
backslash-b is a valid escape. The warning named the harmless case and hid the
harmful one. Found by an outside reviewer.
check-docs-consistency.sh gains a check for control bytes in tracked text files,
deliberately written without hex escapes: a first attempt at the same guard,
assembled the same way, put fifteen raw control bytes including a NUL into the
checker itself and made it flag untouched files. tr understands its own escapes,
so the shell has nothing to mangle. Mutation tested: a planted backspace in
CHANGELOG.md fails the run, a clean tree passes.
sign-release.sh now keeps minisign's stderr and prints it when a signing fails.
Sending it to /dev/null unconditionally turned a wrong password, a full disk and
a corrupt key into one faceless line. The capture idiom was measured: a wrong
password now reports "Wrong password for that key".
* fix(tests): stop testing the runner's package list, and clean the public tree
Three sign-release cases were red in CI and green locally. The script checks
that minisign exists before it checks anything else, and the test workflow
installs only bats, so those cases reported on what the runner had installed
rather than on the script. A stub on PATH removes the dependency; it exits
non-zero on purpose, so a case that ever reached the signing loop would fail
loudly instead of claiming six signatures with no files behind them.
Two more cases asserted the docs checker prints "13 passed". Adding a check
turned that into a failure, which punishes strengthening the gate. They now
assert that nothing failed, which is what the tests are actually about.
Private tracker identifiers had returned to the public tree in two test
comments, one of them added by this very branch, while this release's changelog
claims they were removed. Nothing guarded that: the marker lists in
preflight-check.sh and commit-hygiene.yml did not include them. They do now, and
the comments say what they mean instead of pointing at an identifier a reader
outside cannot resolve.
The release title was 179 characters against a 70 character guideline and would
have been cut mid-word in the sidebar. Both changelog lead sentences are now
short, with the detail moved to the paragraph below; the title comes out at 61.
* fix(release): close four ways the tooling could report work it had not done
Empty notes published green. build-release-notes.sh checked only that the
version heading existed; a heading with no bullets under it - the ordinary
result of opening the section during prep and writing it later - produced a
body that was the bilingual skeleton and nothing else, with rc 0 behind it.
Notes cut at a quoted heading. The section ended on any line starting with
"## [", so a bullet quoting the prescribed "## [X.Y.Z] - YYYY-MM-DD" format
truncated everything after it, silently. The terminator now requires a digit.
A pin reported as written when it was not. _write_pin took sed's exit status as
proof, and sed returns 0 having replaced nothing. The printed value was the
DESIRED hash, not the one in the file, so the line read as confirmation. The pin
is now read back and compared.
An interrupted signing run downgraded to a warning. Preflight judged the
signature tag by the first file the glob returned, and the signing order differs
from the alphabet, so a run interrupted early looked like "all of these are
simply from the previous release" - a warning, which does not block a tag. The
count could not see it either, because the old signatures are always present.
All six tags are read now, and a mixture fails.
sign-release.sh runs the verification even after a partial failure: the mixture
is the dangerous state, and the operator needs to see which files carry which
tag rather than a count.
Each is covered by a test or by a recorded mutation run; the two release-notes
cases fail against the previous script.
|
||
|
|
56d61b8d71
|
fix: compare SHA pins against the tag the installer downloads from (#239)
The lockstep test compared each pin with the helper file sitting next to it
in the working tree. That is a proxy for the real contract, and it holds
only while the tree happens to equal the tag, so it was wrong in both
directions: red on main after a helper was touched without a version bump,
even though every published installer was correct, and green when the pins
had been recomputed from the tree while the tag already existed - the one
state in which a shipped installer refuses the download it should accept.
The installers fetch helpers from
raw.githubusercontent.com/<repo>/${AWG_BRANCH}/<helper>, with AWG_BRANCH
defaulting to v$SCRIPT_VERSION, so a pin's source of truth is the helper's
bytes at that tag. The test and scripts/update-sha-pins.sh now both compare
against the tag when it exists and against the working tree when it does
not, and both state which of the two comparisons they made.
update-sha-pins.sh had to move with the test: preflight runs the bats suite
as step 3 and "update-sha-pins.sh --verify" as step 8, so two different
answers about one state would make preflight green and red at once.
test.yml gets fetch-depth: 0 because the default checkout brings no tags on
branch and pull_request events, leaving the test nothing to compare with.
Measured: full history costs 1 s and 11 MB here.
New tests/test_sha_pin_source_of_truth.bats covers update-sha-pins.sh, which
decides what a pin ought to be and had no tests at all. Six of its seven
cases fail against the previous version of the script.
Known limit, written down rather than hidden: both tools read the local tag
set, so a checkout that never fetched the tag, or whose tag moved under
git tag -f, falls back to the tree comparison. That fallback announces
itself, and RELEASE_PROCESS.md now asks for git fetch --tags --force before
the preflight.
|
||
|
|
c71fc5d73b
|
docs: one source for the OS support matrix, and the same warning in both languages (#238)
The Russian install guide warned that Ubuntu 25.10 is out of support and that there is no reason to pick it for a new server. The English one presented the same release as an ordinary choice and advertised its ARM prebuilt. One language was warned and the other was not, about a machine that faces the internet on a VPN port. Debian 12 was worse: nothing was said in either language, although its regular support ended on 2026-07-11, six weeks before a documentation review walked through these files without noticing, because that review compared the documents with each other rather than with a calendar. Two states could not describe this. Ubuntu 25.10 is an interim release with no extended phase and receives no security updates at all; Debian 12 keeps receiving them through Debian LTS until 2028-06-30. One bucket marked end of life is wrong in both directions. The compatibility table now carries three states with the vendor dates in their own column, and the two languages say the same thing row for row. The surfaces where a reader picks an operating system list what this project suggests, and a line beneath them states that the other two still install and run, so that dropping them from a badge cannot be read as dropping support. The checker held its own literal copy of the matrix, which made a green result mean that the copies agreed rather than that any of them was true. It now derives the set from docs/support-matrix.json, and a second check recomputes each platform's lifecycle from its dates. That catches the class comparing documents cannot catch in principle, where an external fact changes and no document notices. It will sit quiet for nearly two years, long enough to break unnoticed, so it validates its own classifier against nine cases before trusting it, including both sides of the boundary the matrix declares. Inside the installer only advice changed. Two messages recommended reinstalling on Ubuntu 25.10 or Debian 12, which is what a stranded operator reads at the moment of choosing a new system. The gate, the tested list and the workaround machinery for those releases are untouched, so existing installations keep working. No lifecycle notice was added at runtime, because that would mean hardcoding vendor dates into the installer, which is another copy of the matrix and the thing this change exists to remove. Four review rounds found defects in the change itself, each reproduced as a mutation before and after the fix. The staleness warning called a function that does not exist in this script and could never fire. The lifecycle check reported the number of platforms in the file rather than the number compared, so an empty list produced agreement having compared none. Reading the token list with a here-string yielded one empty string rather than an empty array, which made the emptiness guard unreachable and let an empty token reach grep, where it matches every file; a matrix with an empty version passed the entire run. A failure to produce that list left the array undeclared and the ARM coverage check reported agreement over nothing. One exit code meant both a real disagreement and any uncaught exception, so a malformed file sent the reader to recompute dates that were fine. The rule requiring one default platform per family walked the families that were found, which cannot notice one that is absent. Three dates disagreed with the source the matrix names as its own, and one had already reached both READMEs. tests/test_support_matrix_guard.bats covers all of it against deliberately broken copies, with a control on the untouched file. Run against the revision before the last fix, seven of its twelve cases fail. |
||
|
|
bb6fb794af
|
docs: add a machine readable support matrix as the single source of truth (#236)
Facts about which systems this installer targets currently live in twenty three files: both READMEs, both install guides, ADVANCED, CASCADE, WARP-RU, the roadmap, three GitHub templates, two workflows, the installer scripts themselves, and the consistency checker. Nothing arbitrates between them, so they drift apart quietly and a reader cannot tell which copy is current. The matrix carries values only, no prose, so it cannot diverge between the Russian and English documentation the way every other copy can. It stores the basis rather than the conclusion. Vendor dates are recorded and lifecycle is derived from them by a rule written into the file, so a stale lifecycle can be recomputed and caught instead of believed. The same idea covers verification: last_verified names everything that must be rechecked before it may be advanced, not just the field that prompted the edit. Deriving the states from vendor data surfaced something the documentation never said in either language. Debian 12 left regular support on 11 July 2026 and now runs on extended support only. Ubuntu 25.10 left support on 1 July and has no extended phase at all. Those are different situations and they need different advice, which is why the file separates lifecycle from project policy: a platform can be perfectly supported upstream and still not be the pick we suggest by default. The dates come from endoflife.date, the PPA suites match the codename mapping in the installer, and the seven ARM prebuilt ids match the build matrix exactly in both directions. No consumer reads the file yet. Wiring it in is deliberately left separate, because the repository has neither jq nor python anywhere in scripts or workflows, and choosing whether to add one is a decision about the project, not a detail of this file. |
||
|
|
b9f8a70190
|
feat: sign releases and publish them atomically (#233)
Release artifacts now carry detached minisign signatures. The private key stays on the maintainer's machine and never reaches Actions: signing happens offline and the signatures are committed under signing/ before the tag, so the workflow only verifies. A signature that is missing or wrong stops the publication instead of leaving a half-published release behind. release.yml creates the release as a draft, attaches the scripts, their signatures and KEYS.txt, checks that every expected asset is there, and only then publishes. Publishing first and attaching afterwards used to leave releases/latest/download answering 404 for as long as it took somebody to remember the manual step, which is precisely the address users are given. The trusted comment on each signature names the tag and the filename. A signature verifies a byte sequence, not an intention, so without that binding an old and perfectly valid signature paired with its old and perfectly valid file would pass for any tag. commit-hygiene.yml closes the window preflight cannot see: preflight runs at tag time and diffs against main, so a bad commit message is long since merged by then. The new workflow checks the same things while the commit can still be amended. Review of the branch found three defects that would have fired on the first signed tag, all fixed here. verify-signatures.sh could report success having opened no file, because it compared the number of files checked against a number derived from the same list it was checking; the expected set now comes from the scripts at the repository root. The release title was interpolated into a shell command, and this changelog writes flags in backticks, so the title of v5.27.1 would have published with two phrases executed and removed; it now travels through the environment. Publish re-applies the rebuilt title and notes, so fixing a changelog and pushing the tag again no longer republishes the failed run's text. preflight tells a stale signature apart from a wrong one, because signatures stay in the tree between releases and editing any signed script would otherwise turn the gate red on ordinary branches. tests/test_release_signature_guards.bats covers the guard that was silent, control case included: with an intact list the guards must stay quiet. |
||
|
|
f1e1447b02 |
docs(install-vps): add the Russian deployment guide
README, ADVANCED, CHANGELOG, CASCADE and WARP-RU all ship as RU+EN pairs. INSTALL_VPS was English only, so the Russian half of the install and troubleshooting search traffic had nowhere to land. The Russian guide is not a translation of the English one. It keeps the same deployment skeleton but follows what people actually look for: client configs get their own section instead of a subsection, and the ARM prebuilt path is spelled out where it differs from DKMS. On that path there is no dkms, no kernel headers and no ensure-module unit at all, so after a kernel change the tunnel does not come back on its own and repair-module does not help either; the usual way back is to run the installer again. INSTALL_VPS.ru.md joins URL_DOCS in check-docs-consistency.sh so its pinned raw-URL tag is checked against SCRIPT_VERSION like every other document. Without that entry the pin would go stale at the next release with the checks still green. RELEASE_PROCESS now names INSTALL_VPS*.md, which covers the next paired document by construction, and the Russian README links to the Russian guide instead of sending Russian readers to the English one. |
||
|
|
702d3aff5b
|
Release v5.18.1: --force port change, full-tunnel iOS ::/0, dual DNS, low ports
Bug-fix release. Four fixes plus documentation. - install --force --port=N now changes the server port (was silently ignored: the render re-read the old ListenPort). - full-tunnel clients get 0.0.0.0/0, ::/0 so AmneziaVPN on iOS accepts the all-traffic mode; manage regen upgrades non-customized clients too. - default client DNS is now the 1.1.1.1, 1.0.0.1 pair. - --port accepts ports 1-65535 (was 1024-65535) so 443/80/53 work for DPI evasion on mobile carriers. Docs: CHANGELOG, S3/S4 range fix, stale issue link cleanup, Ubuntu 26.04 in the subtitle, --force re-run FAQ, a mobile-port note. Live-tested on Debian 13 (x86_64) and Ubuntu 26.04 (ARM64, native IPv6). |
||
|
|
ed8945d54d
|
feat(obfuscation): pass special-junk params I2-I5 through to clients (#71)
Wire all five CPS special-junk params I1-I5 from the server awg0.conf into client configs (.conf, QR, vpn://). Previously only I1 reached clients; I2-I5 were hard-coded empty and undeliverable. Scope = variant 1 of #71: the admin sets I2-I5 in awg0.conf and manage regen distributes them; no new CLI flags. RU/EN in lockstep, SHA pins recomputed, docs (ADVANCED/ROADMAP/CHANGELOG RU+EN), new bats coverage. Release v5.18.0. |
||
|
|
313b0007d1
|
feat(firewall): clamp TCP MSS to the tunnel MTU (v5.17.0) (#139)
Add an automatic TCPMSS --set-mss rule (mangle FORWARD, both directions, SYN only) to the server PostUp/PostDown, derived from AWG_MTU (1240 v4 / 1220 v6), fixing the PMTU blackhole on mobile/double-NAT/cascade paths. Ships v5.17.0 with tests, SHA pins, CHANGELOG and docs. Smoke-tested on x86_64 and ARM64 (IPv4 + IPv6). |
||
|
|
8152bd21c0
|
docs: refresh ROADMAP recently-shipped with v5.16 themes and companion guides (#126)
Add three evergreen themes to Recently shipped / Уже сделано (RU+EN): security and reliability hardening, correct iOS behavior in the default routing mode, and the companion guides (official-app comparison and the two-server cascade). Keeps the page theme-based, not a dated changelog. |
||
|
|
902f4d787b
|
release: v5.15.6 - input validation, atomicity and a JSON status field
A hardening and quality release that finalizes two accumulated workstreams. Code-audit hardening (manage/awg_common/install): - modify validates DNS as real IPv4/IPv6; octet-range check on the detected public IP - --expires validated before client creation; --psk fails closed - atomic .vpnuri and QR writes via the shared safe-temp helper; one shared client-artifact cleanup - content-aware expiry cron; restore guards for an empty server/clients backup - INT/TERM abort the script with exit 130/143 instead of falling through Machine-readable status (additive, backward-compatible): - list --json and stats --json also emit a stable status_code enum (active | recent | inactive | no_handshake | key_error | no_data); the localized status field is kept Docs and process: - accurate CLI help (--endpoint FQDN/IPv4/[IPv6], --no-tweaks note), README diagnose/repair-module rows - ARM coverage for Ubuntu 26.04 (DKMS); docs-check enforces the OS x arch x prebuilt-target matrix - CI badges, signing-doc cleanup, clearer issue/PR templates Release mechanics: version and date bumped to 5.15.6 across the six scripts, helper SHA pins recomputed, CHANGELOG (RU + EN) updated, pinned raw-URL tags and README badges bumped. Default install behavior and the support matrix are unchanged. |
||
|
|
13203c6293
|
v5.15.3 - maintenance release (validator hardening, audit fixes, CI tooling) (#100)
Hardening release after four rounds of external code and documentation audits: installer input validators brought to canonical parity, manage restore/modify correctness fixes, atomic file operations, reproducible ARM builds with a pinned module ref and build manifest, bilingual release notes built by release.yml, an 8x faster Unicode-aware docs consistency check, and documentation accuracy fixes across README, INSTALL_VPS, ADVANCED, RELEASE_PROCESS and the Code of Conduct. Test suite grows to 788 checks; live-tested on clean Ubuntu 24.04 x86_64, Ubuntu 26.04 ARM64 and Debian 13 VPSes including real cross-continent AWG 2.0 handshakes. |
||
|
|
1cbee098ca
|
v5.15.1 - maintenance release (audit fixes, IPv6 hardening, release gate)
Maintenance release after external code and documentation audits. No new features; hardens the v5.15.0 dual-stack IPv6 work, tightens several manage commands, fixes correctness and robustness issues, and adds a release preflight gate plus a docs-consistency check. Behavior change: split tunnel + IPv6 mirrors the IPv4 intent - a custom ALLOWED_IPS keeps that IPv4 split and adds only the tunnel ULA for IPv6 instead of forcing a full ::/0 route. A full tunnel still gets ::/0 (native IPv6) or the ULA. Fixed: vpn:// URI carries the server's real MTU/keepalive/DNS; stricter native-IPv6 detection (global non-ULA address and default route) with the host IPv6 stack re-enabled before detection; install fails fast on apt update errors; manage modify validates Endpoint/AllowedIPs; manage add is safe against name reuse and cleans partial artifacts; manage restore prunes stale clients/keys and recreates the expiry dir; manage help exit codes; manage --json keeps stdout pure JSON; log messages stop doubling percent signs. Docs/process: subnet and OS help accuracy, list --json documented, changelog compare-links and anchors restored, SECURITY/CONTRIBUTING refreshed, public RELEASE_PROCESS.md, release publish gated behind a full preflight job, new docs-consistency workflow, signing design aligned with the asset draft. Version bumped to 5.15.1 across all six scripts; SHA pins recomputed. |
||
|
|
3d974af9e7 |
fix: address second-pass review findings (HIGH/MEDIUM bundle)
Second independent review of the three preceding commits surfaced:
1. (HIGH) tests/test_v5140_public_ip_services.bats - SC2318 in curl mocks:
`local args=("$@") url="${args[$((${#args[@]} - 1))]}"` references the
array on the same `local` line where it is being assigned. ShellCheck
flags this and the assignment is unreliable. Split into two `local`
statements. Bats suite still passes 11/11 after the fix.
2. (MEDIUM) ADVANCED.md / ADVANCED.en.md - the legacy split-tunneling
paragraph still claimed the default AllowedIPs = 0.0.0.0/0 covers the
tunnel subnet automatically. README was already corrected in
|
||
|
|
8c14921f32 |
docs(security): release signing design (minisign) - planning for v5.14+
Spec for adding detached minisign signatures to installer/management scripts and tagged releases. The proposal: - Keypair generated offline by the maintainer, public key published as KEYS.txt in the repo root, private key NEVER exposed to GitHub Actions (this is the whole point - signing must be local to the maintainer). - Per-release signing happens on the maintainer's machine before 'git push origin vX.Y.Z'; .minisig files attached to the GitHub Release as assets either manually (gh release upload) or via the draft workflow at docs/release-sign.yml.draft. - User-side verification: 'minisign -V -p KEYS.txt -m <script> -x <sig>'. This commit is design + drafts only. Workflow stays under docs/ until the public key is committed and signatures of pre-release assets are tested. SECURITY.md gains a 'Release integrity (planned)' section. Activation is user-action-blocked (maintainer must generate the offline keypair). Closes implementation gap surfaced by competitor analysis 2026-05-18 (pwnnex/ByeByeVPN ships signed releases + SBOM). Files added: docs/SIGNING_DESIGN.md - threat model, tool choice, signing flow docs/release-sign.yml.draft - GitHub Actions workflow draft SECURITY.md +6 - 'Release integrity (planned)' section |