[GH-ISSUE #3063] VPN client management silently fails when SSH user has docker group but not sudo/wheel #1412

Open
opened 2026-10-13 20:42:01 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @snarknn on GitHub (Aug 26, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3063

Describe the bug
All VPN client management operations (listing clients, adding, revoking) silently fail when the SSH user is a member of the docker group but NOT the sudo/wheel group. The commands use sudo docker ... unconditionally, so they require sudo even though docker group membership would be sufficient.

The user sees no explicit error — the client list simply shows as empty, and new client configs appear to be created but the VPN client cannot connect.

To Reproduce

  1. On the server, create a user that is in the docker group but NOT in sudo/wheel:
    sudo adduser amnezia
    sudo usermod -aG docker amnezia
    
    (Do NOT add to sudo or wheel group)
  2. Connect to the server from Amnezia VPN client using this user
  3. The initial container installation may have been done previously as root or a sudo-capable user
  4. Try to list VPN clients — the list is empty (no error shown)
  5. Try to add a new VPN client — the config appears to be created, but the VPN client cannot connect

Expected behavior
The client should either:

  • Detect that the user has docker group access and use docker instead of sudo docker for all commands, OR
  • Provide a clear error message indicating that sudo access is required and what specific permissions are needed

Root cause analysis (from source code)

The issue has two parts:

  1. All docker commands unconditionally use sudo docker — there is no conditional logic anywhere in the codebase that detects docker group membership and skips sudo. Every script and C++ SSH command uses sudo docker exec, sudo docker run, sudo docker build, etc.

  2. isUserInSudo() is only called during initial container setup (installController.cpp:110 in setupContainer()). It is NOT called during:

    • Listing VPN clients (usersController.cpp — updateClients())
    • Adding VPN clients (appendClient())
    • Revoking VPN clients (revokeClient(), revokeOpenVpn(), revokeWireGuard(), revokeXray())
    • Renaming VPN clients (renameClient())
    • Container restart/remove/status queries

    So the sudo check passes during initial install (if done as root), but all subsequent client management operations fail silently because sudo docker exec commands fail for a docker-group-only user.

Concrete list of affected commands (executed via SSH on the server):

Operation Command that fails
List WireGuard/AWG clients sudo docker exec -i <container> bash -c 'wg show all'
List OpenVPN clients sudo docker exec -i <container> bash -c 'ls /opt/amnezia/openvpn/pki/issued'
Add OpenVPN client sudo docker exec -i <container> bash -c 'cd /opt/amnezia/openvpn && easyrsa sign-req client ...'
Revoke OpenVPN client sudo docker exec -i <container> bash -c 'cd /opt/amnezia/openvpn; easyrsa revoke ...; easyrsa gen-crl'
Revoke WireGuard/AWG client sudo docker exec -i <container> bash -c 'wg syncconf wg0 <(...)'
Revoke Xray client sudo docker restart <container>
Read client config from container sudo docker exec -i <container> cat <path>
Upload file to container sudo docker cp <tmpfile> <container>:/<path>
Restart container sudo docker restart <container>
Query container status sudo docker inspect --format '...' <container>
Enable/disable container sudo docker start/stop <container>

Proposed fix

Two options:

Option A (minimal): In sshSession.cpp and C++ code, detect whether the user can run docker directly (by running docker ps without sudo as a probe), and if so, use docker instead of sudo docker for all subsequent commands. This would allow docker-group-only users to manage existing containers.

Option B (comprehensive): Support a fine-grained sudoers configuration where the user has passwordless sudo for specific commands:

amnezia ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/systemctl, /usr/sbin/sysctl, /usr/sbin/iptables, /usr/bin/conntrack, /usr/sbin/ss, /usr/bin/shred, /usr/bin/mkdir, /usr/bin/chown, /usr/sbin/reboot

But this still requires the user to be in the sudo/wheel group due to the isUserInSudo() check, which looks for group membership rather than testing actual sudo capability.

The most practical fix would be to:

  1. Make isUserInSudo() test actual sudo -n capability rather than group membership
  2. Allow docker-group-only users to manage existing containers (skip sudo for docker commands when docker group access is available)

Related issues:

  • #969 — Feature request for managing containers without sudo (open since Aug 2024)
  • #2111 — False positive "sudoers" error on GCP (related to group name detection)

Log files
(Attach log files if available)

Desktop (please complete the following information):

  • OS: [e.g. Windows 11]
  • Version [5.0.1.5]

Server (please complete the following information):

  • OS: [Ubuntu 24.04]
Originally created by @snarknn on GitHub (Aug 26, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3063 **Describe the bug** All VPN client management operations (listing clients, adding, revoking) silently fail when the SSH user is a member of the `docker` group but NOT the `sudo`/`wheel` group. The commands use `sudo docker ...` unconditionally, so they require sudo even though docker group membership would be sufficient. The user sees no explicit error — the client list simply shows as empty, and new client configs appear to be created but the VPN client cannot connect. **To Reproduce** 1. On the server, create a user that is in the `docker` group but NOT in `sudo`/`wheel`: ```bash sudo adduser amnezia sudo usermod -aG docker amnezia ``` (Do NOT add to `sudo` or `wheel` group) 2. Connect to the server from Amnezia VPN client using this user 3. The initial container installation may have been done previously as root or a sudo-capable user 4. Try to list VPN clients — the list is empty (no error shown) 5. Try to add a new VPN client — the config appears to be created, but the VPN client cannot connect **Expected behavior** The client should either: - Detect that the user has docker group access and use `docker` instead of `sudo docker` for all commands, OR - Provide a clear error message indicating that sudo access is required and what specific permissions are needed **Root cause analysis (from source code)** The issue has two parts: 1. **All docker commands unconditionally use `sudo docker`** — there is no conditional logic anywhere in the codebase that detects docker group membership and skips sudo. Every script and C++ SSH command uses `sudo docker exec`, `sudo docker run`, `sudo docker build`, etc. 2. **`isUserInSudo()` is only called during initial container setup** (`installController.cpp:110` in `setupContainer()`). It is NOT called during: - Listing VPN clients (`usersController.cpp` — `updateClients()`) - Adding VPN clients (`appendClient()`) - Revoking VPN clients (`revokeClient()`, `revokeOpenVpn()`, `revokeWireGuard()`, `revokeXray()`) - Renaming VPN clients (`renameClient()`) - Container restart/remove/status queries So the sudo check passes during initial install (if done as root), but all subsequent client management operations fail silently because `sudo docker exec` commands fail for a docker-group-only user. **Concrete list of affected commands** (executed via SSH on the server): | Operation | Command that fails | |-----------|-------------------| | List WireGuard/AWG clients | `sudo docker exec -i <container> bash -c 'wg show all'` | | List OpenVPN clients | `sudo docker exec -i <container> bash -c 'ls /opt/amnezia/openvpn/pki/issued'` | | Add OpenVPN client | `sudo docker exec -i <container> bash -c 'cd /opt/amnezia/openvpn && easyrsa sign-req client ...'` | | Revoke OpenVPN client | `sudo docker exec -i <container> bash -c 'cd /opt/amnezia/openvpn; easyrsa revoke ...; easyrsa gen-crl'` | | Revoke WireGuard/AWG client | `sudo docker exec -i <container> bash -c 'wg syncconf wg0 <(...)'` | | Revoke Xray client | `sudo docker restart <container>` | | Read client config from container | `sudo docker exec -i <container> cat <path>` | | Upload file to container | `sudo docker cp <tmpfile> <container>:/<path>` | | Restart container | `sudo docker restart <container>` | | Query container status | `sudo docker inspect --format '...' <container>` | | Enable/disable container | `sudo docker start/stop <container>` | **Proposed fix** Two options: **Option A (minimal):** In `sshSession.cpp` and C++ code, detect whether the user can run `docker` directly (by running `docker ps` without sudo as a probe), and if so, use `docker` instead of `sudo docker` for all subsequent commands. This would allow docker-group-only users to manage existing containers. **Option B (comprehensive):** Support a fine-grained sudoers configuration where the user has passwordless sudo for specific commands: ``` amnezia ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/systemctl, /usr/sbin/sysctl, /usr/sbin/iptables, /usr/bin/conntrack, /usr/sbin/ss, /usr/bin/shred, /usr/bin/mkdir, /usr/bin/chown, /usr/sbin/reboot ``` But this still requires the user to be in the `sudo`/`wheel` group due to the `isUserInSudo()` check, which looks for group membership rather than testing actual sudo capability. The most practical fix would be to: 1. Make `isUserInSudo()` test actual `sudo -n` capability rather than group membership 2. Allow docker-group-only users to manage existing containers (skip sudo for docker commands when docker group access is available) **Related issues:** - #969 — Feature request for managing containers without sudo (open since Aug 2024) - #2111 — False positive "sudoers" error on GCP (related to group name detection) **Log files** (Attach log files if available) **Desktop (please complete the following information):** - OS: [e.g. Windows 11] - Version [5.0.1.5] **Server (please complete the following information):** - OS: [Ubuntu 24.04]
Author
Owner

@rasolAAaa commented on GitHub (Aug 27, 2026):

باتشکر از زحمات شما ممنونم چنین است که دیگر من نمی‌توانم متصل شوم باکمال
تشکر

در تاریخ پنجشنبه 27 اوت 2026،‏ 1:57 snarknn @.***> نوشت:

snarknn created an issue (amnezia-vpn/amnezia-client#3063)
https://github.com/amnezia-vpn/amnezia-client/issues/3063

Describe the bug
All VPN client management operations (listing clients, adding, revoking)
silently fail when the SSH user is a member of the docker group but NOT
the sudo/wheel group. The commands use sudo docker ... unconditionally,
so they require sudo even though docker group membership would be
sufficient.

The user sees no explicit error — the client list simply shows as empty,
and new client configs appear to be created but the VPN client cannot
connect.

To Reproduce

  1. On the server, create a user that is in the docker group but NOT in
    sudo/wheel:

sudo adduser amnezia
sudo usermod -aG docker amnezia

(Do NOT add to sudo or wheel group)
2. Connect to the server from Amnezia VPN client using this user
3. The initial container installation may have been done previously as
root or a sudo-capable user
4. Try to list VPN clients — the list is empty (no error shown)
5. Try to add a new VPN client — the config appears to be created, but
the VPN client cannot connect

Expected behavior
The client should either:

  • Detect that the user has docker group access and use docker instead
    of sudo docker for all commands, OR
  • Provide a clear error message indicating that sudo access is
    required and what specific permissions are needed

Root cause analysis (from source code)

The issue has two parts:

All docker commands unconditionally use sudo docker — there is no
conditional logic anywhere in the codebase that detects docker group
membership and skips sudo. Every script and C++ SSH command uses sudo
docker exec, sudo docker run, sudo docker build, etc.
2.

isUserInSudo() is only called during initial container setup (
installController.cpp:110 in setupContainer()). It is NOT called
during:

  • Listing VPN clients (usersController.cpp — updateClients())
    • Adding VPN clients (appendClient())
    • Revoking VPN clients (revokeClient(), revokeOpenVpn(),
      revokeWireGuard(), revokeXray())
    • Renaming VPN clients (renameClient())
    • Container restart/remove/status queries

So the sudo check passes during initial install (if done as root), but
all subsequent client management operations fail silently because sudo
docker exec commands fail for a docker-group-only user.

Concrete list of affected commands (executed via SSH on the server):
Operation Command that fails
List WireGuard/AWG clients sudo docker exec -i bash -c 'wg
show all'
List OpenVPN clients sudo docker exec -i bash -c 'ls
/opt/amnezia/openvpn/pki/issued'
Add OpenVPN client sudo docker exec -i bash -c 'cd
/opt/amnezia/openvpn && easyrsa sign-req client ...'
Revoke OpenVPN client sudo docker exec -i bash -c 'cd
/opt/amnezia/openvpn; easyrsa revoke ...; easyrsa gen-crl'
Revoke WireGuard/AWG client sudo docker exec -i bash -c 'wg
syncconf wg0 <(...)'
Revoke Xray client sudo docker restart
Read client config from container sudo docker exec -i cat

Upload file to container sudo docker cp :/
Restart container sudo docker restart
Query container status sudo docker inspect --format '...'
Enable/disable container sudo docker start/stop

Proposed fix

Two options:

Option A (minimal): In sshSession.cpp and C++ code, detect whether the
user can run docker directly (by running docker ps without sudo as a
probe), and if so, use docker instead of sudo docker for all subsequent
commands. This would allow docker-group-only users to manage existing
containers.

Option B (comprehensive): Support a fine-grained sudoers configuration
where the user has passwordless sudo for specific commands:

amnezia ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/systemctl, /usr/sbin/sysctl, /usr/sbin/iptables, /usr/bin/conntrack, /usr/sbin/ss, /usr/bin/shred, /usr/bin/mkdir, /usr/bin/chown, /usr/sbin/reboot

But this still requires the user to be in the sudo/wheel group due to the
isUserInSudo() check, which looks for group membership rather than
testing actual sudo capability.

The most practical fix would be to:

  1. Make isUserInSudo() test actual sudo -n capability rather than
    group membership
  2. Allow docker-group-only users to manage existing containers (skip
    sudo for docker commands when docker group access is available)

Related issues:

Log files
(Attach log files if available)

Desktop (please complete the following information):

  • OS: [e.g. Windows 11]
  • Version [5.0.1.5]

Server (please complete the following information):

  • OS: [Ubuntu 24.04]

—
Reply to this email directly, view it on GitHub
https://github.com/amnezia-vpn/amnezia-client/issues/3063?email_source=notifications&email_token=BIQMEYRETOWYT7R6RPZE6535L5I3RA5CNFSL4Z3JMQ5C6L3HNF2C22DVMIXUS43TOVSS6NJSGYYTMMBWHE2DNJTSMVQXG33OVJZXKYTTMNZGSYTFMSSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/BIQMEYRNZ665ALTAHVIPONL5L5I3RAVCNFSNUABFKJSXA33TNF2G64TZHMZTCNJQGM2TGNZRHNEXG43VMU5TKMRWGE3DANRZGQ3KC5QC
.
You are receiving this because you are subscribed to this thread.Message
ID: @.***>

<!-- gh-comment-id:5434874861 --> @rasolAAaa commented on GitHub (Aug 27, 2026): باتشکر از زحمات شما ممنونم چنین است که دیگر من نمی‌توانم متصل شوم باکمال تشکر در تاریخ پنجشنبه 27 اوت 2026،‏ 1:57 snarknn ***@***.***> نوشت: > *snarknn* created an issue (amnezia-vpn/amnezia-client#3063) > <https://github.com/amnezia-vpn/amnezia-client/issues/3063> > > *Describe the bug* > All VPN client management operations (listing clients, adding, revoking) > silently fail when the SSH user is a member of the docker group but NOT > the sudo/wheel group. The commands use sudo docker ... unconditionally, > so they require sudo even though docker group membership would be > sufficient. > > The user sees no explicit error — the client list simply shows as empty, > and new client configs appear to be created but the VPN client cannot > connect. > > *To Reproduce* > > 1. On the server, create a user that is in the docker group but NOT in > sudo/wheel: > > sudo adduser amnezia > sudo usermod -aG docker amnezia > > (Do NOT add to sudo or wheel group) > 2. Connect to the server from Amnezia VPN client using this user > 3. The initial container installation may have been done previously as > root or a sudo-capable user > 4. Try to list VPN clients — the list is empty (no error shown) > 5. Try to add a new VPN client — the config appears to be created, but > the VPN client cannot connect > > *Expected behavior* > The client should either: > > - Detect that the user has docker group access and use docker instead > of sudo docker for all commands, OR > - Provide a clear error message indicating that sudo access is > required and what specific permissions are needed > > *Root cause analysis (from source code)* > > The issue has two parts: > > 1. > > *All docker commands unconditionally use sudo docker* — there is no > conditional logic anywhere in the codebase that detects docker group > membership and skips sudo. Every script and C++ SSH command uses sudo > docker exec, sudo docker run, sudo docker build, etc. > 2. > > *isUserInSudo() is only called during initial container setup* ( > installController.cpp:110 in setupContainer()). It is NOT called > during: > - Listing VPN clients (usersController.cpp — updateClients()) > - Adding VPN clients (appendClient()) > - Revoking VPN clients (revokeClient(), revokeOpenVpn(), > revokeWireGuard(), revokeXray()) > - Renaming VPN clients (renameClient()) > - Container restart/remove/status queries > > So the sudo check passes during initial install (if done as root), but > all subsequent client management operations fail silently because sudo > docker exec commands fail for a docker-group-only user. > > *Concrete list of affected commands* (executed via SSH on the server): > Operation Command that fails > List WireGuard/AWG clients sudo docker exec -i <container> bash -c 'wg > show all' > List OpenVPN clients sudo docker exec -i <container> bash -c 'ls > /opt/amnezia/openvpn/pki/issued' > Add OpenVPN client sudo docker exec -i <container> bash -c 'cd > /opt/amnezia/openvpn && easyrsa sign-req client ...' > Revoke OpenVPN client sudo docker exec -i <container> bash -c 'cd > /opt/amnezia/openvpn; easyrsa revoke ...; easyrsa gen-crl' > Revoke WireGuard/AWG client sudo docker exec -i <container> bash -c 'wg > syncconf wg0 <(...)' > Revoke Xray client sudo docker restart <container> > Read client config from container sudo docker exec -i <container> cat > <path> > Upload file to container sudo docker cp <tmpfile> <container>:/<path> > Restart container sudo docker restart <container> > Query container status sudo docker inspect --format '...' <container> > Enable/disable container sudo docker start/stop <container> > > *Proposed fix* > > Two options: > > *Option A (minimal):* In sshSession.cpp and C++ code, detect whether the > user can run docker directly (by running docker ps without sudo as a > probe), and if so, use docker instead of sudo docker for all subsequent > commands. This would allow docker-group-only users to manage existing > containers. > > *Option B (comprehensive):* Support a fine-grained sudoers configuration > where the user has passwordless sudo for specific commands: > > amnezia ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/systemctl, /usr/sbin/sysctl, /usr/sbin/iptables, /usr/bin/conntrack, /usr/sbin/ss, /usr/bin/shred, /usr/bin/mkdir, /usr/bin/chown, /usr/sbin/reboot > > But this still requires the user to be in the sudo/wheel group due to the > isUserInSudo() check, which looks for group membership rather than > testing actual sudo capability. > > The most practical fix would be to: > > 1. Make isUserInSudo() test actual sudo -n capability rather than > group membership > 2. Allow docker-group-only users to manage existing containers (skip > sudo for docker commands when docker group access is available) > > *Related issues:* > > - #969 <https://github.com/amnezia-vpn/amnezia-client/issues/969> — > Feature request for managing containers without sudo (open since Aug 2024) > - #2111 <https://github.com/amnezia-vpn/amnezia-client/issues/2111> — > False positive "sudoers" error on GCP (related to group name detection) > > *Log files* > (Attach log files if available) > > *Desktop (please complete the following information):* > > - OS: [e.g. Windows 11] > - Version [5.0.1.5] > > *Server (please complete the following information):* > > - OS: [Ubuntu 24.04] > > — > Reply to this email directly, view it on GitHub > <https://github.com/amnezia-vpn/amnezia-client/issues/3063?email_source=notifications&email_token=BIQMEYRETOWYT7R6RPZE6535L5I3RA5CNFSL4Z3JMQ5C6L3HNF2C22DVMIXUS43TOVSS6NJSGYYTMMBWHE2DNJTSMVQXG33OVJZXKYTTMNZGSYTFMSSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L>, > or unsubscribe > <https://github.com/notifications/unsubscribe-auth/BIQMEYRNZ665ALTAHVIPONL5L5I3RAVCNFSNUABFKJSXA33TNF2G64TZHMZTCNJQGM2TGNZRHNEXG43VMU5TKMRWGE3DANRZGQ3KC5QC> > . > You are receiving this because you are subscribed to this thread.Message > ID: ***@***.***> >
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#1412
No description provided.