diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..efa411b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +# Changelog + +All notable changes to nm-sshuttle are listed here. The format follows +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project +uses [semantic versioning](https://semver.org/). + +## [0.1.0] - 2026-10-11 + +The first release. + +### Added + +- NetworkManager VPN plugin that runs an sshuttle tunnel, so the tunnel is a + toggle in GNOME Quick Settings and a connection in `nmcli`. sshuttle runs + as root in its own systemd unit; only `ssh` runs as the user, with their + own `~/.ssh/config`, `ProxyJump`, `known_hosts` and agent. +- Fail-closed guard: traffic to the tunnelled networks is blocked while the + tunnel is down. +- Lifecycle handling: reconnect with backoff after suspend, roaming, a + captive portal, a dropped connection or a locked screen; health checks, + with an optional `probe`, notice a tunnel that is up but stuck; another + VPN's activation triggers an immediate reconnect. +- Split DNS through systemd-resolved, or all lookups through the tunnel. +- IPv4 and IPv6 networks, exclusions and first hops. +- UDP through the tunnel with `method=tproxy`. +- Up to 8 tunnels at once, one plugin instance per activation; a profile that + conflicts with an active one is refused. +- The `nm-sshuttle` command with `add`, `check`, `list` and `remove` to + manage profiles as the user. +- GTK4 editor for GNOME Settings (`nm-sshuttle-gnome`), validating profiles + with the same rules as the plugin. +- Packages: RPMs for Fedora 43 and 44 from a signed dnf repository on GitHub + Pages (`nm-sshuttle-release` sets it up), and Debian 13 and Ubuntu 26.04 + packages built by CI. +- User guide and design documentation, a lab that checks the sshuttle and + kernel behaviour the design relies on, and VM tests that run in CI. + +### Known limits + +- The tunnel's DNS needs systemd-resolved. Without it (NetworkManager + writing `/etc/resolv.conf` itself), `dns split` sends every lookup to the + tunnel's resolvers, and a resolver entry that NetworkManager fails to + remove can stay until it restarts. The case is described in the design + (section 4.5) but not tested on a VM. +- There is no Debian or Ubuntu package repository; take the `.deb` files + from a CI run. + +[0.1.0]: https://github.com/dennisklein/nm-sshuttle/releases/tag/v0.1.0 diff --git a/debian/changelog b/debian/changelog index ba3ee45..697d851 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -nm-sshuttle (0.1.0~dev0-1) unstable; urgency=medium +nm-sshuttle (0.1.0-1) unstable; urgency=medium * Initial package. - -- Dennis Klein Sat, 10 Oct 2026 20:00:00 +0000 + -- Dennis Klein Sat, 10 Oct 2026 20:00:00 +0000 diff --git a/debian/control b/debian/control index 4e05851..365ba97 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: nm-sshuttle Section: net Priority: optional -Maintainer: Dennis Klein +Maintainer: Dennis Klein Build-Depends: debhelper-compat (= 13), dh-python, diff --git a/meson.build b/meson.build index 0d4297d..a4306bc 100644 --- a/meson.build +++ b/meson.build @@ -7,7 +7,7 @@ # Paths follow design ยง4.1. NetworkManager's directories are fixed under # /usr/lib, whatever the prefix: NM looks for VPN plugins and its packaged # conf.d nowhere else. -project('nm-sshuttle', version: '0.1.0.dev0', license: 'MIT', meson_version: '>= 0.64') +project('nm-sshuttle', version: '0.1.0', license: 'MIT', meson_version: '>= 0.64') python = import('python').find_installation('python3') prefix = get_option('prefix') diff --git a/nm_sshuttle/__init__.py b/nm_sshuttle/__init__.py index b1ee59d..28cda9f 100644 --- a/nm_sshuttle/__init__.py +++ b/nm_sshuttle/__init__.py @@ -1,4 +1,4 @@ # SPDX-License-Identifier: MIT """NetworkManager VPN service plugin for sshuttle (docs/design.md).""" -__version__ = "0.1.0.dev0" +__version__ = "0.1.0" diff --git a/packaging/README.md b/packaging/README.md index 73ffd88..be5e475 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -37,7 +37,9 @@ with a throwaway key and deploy nothing. ### Releasing -Push an annotated tag whose version is the release's: +Merge the release's version into `main` first: `meson.build`, +`nm_sshuttle/__init__.py`, the two specs, `debian/changelog` and +`CHANGELOG.md`. Then push an annotated tag whose version is the release's: ```console $ git tag -a v0.1.0 -m 'nm-sshuttle 0.1.0' diff --git a/packaging/nm-sshuttle-release/nm-sshuttle-release.spec b/packaging/nm-sshuttle-release/nm-sshuttle-release.spec index 8a7add2..c93cc67 100644 --- a/packaging/nm-sshuttle-release/nm-sshuttle-release.spec +++ b/packaging/nm-sshuttle-release/nm-sshuttle-release.spec @@ -31,5 +31,5 @@ install -Dpm 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/pki/rpm-gpg/RPM-GPG-KEY- %{_sysconfdir}/pki/rpm-gpg/RPM-GPG-KEY-nm-sshuttle %changelog -* Sun Oct 11 2026 Dennis Klein - 1-1 +* Sun Oct 11 2026 Dennis Klein - 1-1 - Initial package diff --git a/packaging/rpm/nm-sshuttle-gnome.spec b/packaging/rpm/nm-sshuttle-gnome.spec index 69d4e2e..4420f47 100644 --- a/packaging/rpm/nm-sshuttle-gnome.spec +++ b/packaging/rpm/nm-sshuttle-gnome.spec @@ -3,7 +3,7 @@ # The editor for GNOME Settings, from the same tarball as nm-sshuttle.spec. It # has its own spec because it is compiled code and nm-sshuttle is noarch. Name: nm-sshuttle-gnome -Version: 0.1.0~dev0 +Version: 0.1.0 Release: 1%{?dist} Summary: GNOME Settings editor for nm-sshuttle profiles License: MIT @@ -53,5 +53,5 @@ xvfb-run -a %{__meson} test -C %{_vpath_builddir} --no-rebuild --print-errorlogs %{_libdir}/NetworkManager/libnm-vpn-plugin-sshuttle.so %changelog -* Sun Oct 11 2026 Dennis Klein - 0.1.0~dev0-1 +* Sun Oct 11 2026 Dennis Klein - 0.1.0-1 - Initial package diff --git a/packaging/rpm/nm-sshuttle.spec b/packaging/rpm/nm-sshuttle.spec index ba13a96..ee50b74 100644 --- a/packaging/rpm/nm-sshuttle.spec +++ b/packaging/rpm/nm-sshuttle.spec @@ -2,7 +2,7 @@ %global nm_libdir %{_prefix}/lib/NetworkManager Name: nm-sshuttle -Version: 0.1.0~dev0 +Version: 0.1.0 Release: 1%{?dist} Summary: NetworkManager VPN plugin that tunnels with sshuttle License: MIT @@ -82,5 +82,5 @@ fi %{_unitdir}/nm-sshuttle-tunnel@.service %changelog -* Sat Oct 10 2026 Dennis Klein - 0.1.0~dev0-1 +* Sat Oct 10 2026 Dennis Klein - 0.1.0-1 - Initial package diff --git a/packaging/smoke-test.sh b/packaging/smoke-test.sh index 86a2930..c82f428 100755 --- a/packaging/smoke-test.sh +++ b/packaging/smoke-test.sh @@ -17,8 +17,10 @@ dnf -y install "$base/nm-sshuttle-release.noarch.rpm" # nm-sshuttle.repo points at the public site; follow the site under test # instead. --allowerasing: the container has systemd-standalone-tmpfiles, # which conflicts with the systemd that systemd-resolved needs; a real system -# has the full systemd. -dnf -y install --allowerasing --setopt="nm-sshuttle.baseurl=$base/rpm/fedora/\$releasever/\$basearch/" \ +# has the full systemd. No weak dependencies: GTK's media codecs include +# openh264, which comes from a third-party host that a hosted runner fails to +# reach now and then, and nothing here uses them. +dnf -y install --allowerasing --setopt=install_weak_deps=False --setopt="nm-sshuttle.baseurl=$base/rpm/fedora/\$releasever/\$basearch/" \ nm-sshuttle nm-sshuttle-gnome rpm -q --qf '%{NAME}-%{VERSION}-%{RELEASE}: %{SIGPGP:pgpsig}\n' \ diff --git a/scripts/signing-key.sh b/scripts/signing-key.sh index b78a078..f897b8d 100755 --- a/scripts/signing-key.sh +++ b/scripts/signing-key.sh @@ -35,11 +35,11 @@ # the next publish sign everything with the new key. # 3. After that publish, --retire removes the old key. # -# Env: NM_SSHUTTLE_SIGNING_UID key user ID (default: nm-sshuttle package signing ) +# Env: NM_SSHUTTLE_SIGNING_UID key user ID (default: nm-sshuttle package signing ) # NM_SSHUTTLE_REPO GitHub repository (default: dennisklein/nm-sshuttle) set -euo pipefail -uid=${NM_SSHUTTLE_SIGNING_UID:-nm-sshuttle package signing } +uid=${NM_SSHUTTLE_SIGNING_UID:-nm-sshuttle package signing } repo=${NM_SSHUTTLE_REPO:-dennisklein/nm-sshuttle} environment=rpm-signing secret=RPM_SIGNING_KEY diff --git a/test-vm/gnome-editor-protocol.md b/test-vm/gnome-editor-protocol.md index e59b633..e729493 100644 --- a/test-vm/gnome-editor-protocol.md +++ b/test-vm/gnome-editor-protocol.md @@ -29,7 +29,7 @@ than "Expect" is a finding, even if it looks harmless: write down what you saw. $ sudo dnf install git rpm-build dnf5-plugins $ git clone -b claude/project-thread-c5oyfl https://github.com/dennisklein/nm-sshuttle ~/src/nm-sshuttle $ cd ~/src/nm-sshuttle -$ version=0.1.0~dev0 +$ version=0.1.0 $ mkdir -p ~/rpmbuild/SOURCES $ git archive --format=tar.gz --prefix="nm-sshuttle-$version/" \ -o ~/rpmbuild/SOURCES/"nm-sshuttle-$version.tar.gz" HEAD