# openvpn-ui is a web admin panel that sits in front of an OpenVPN server

> openvpn-ui is a Go web interface for administering an OpenVPN server, generating and revoking client certificates through EasyRSA, and editing the server configuration from a browser. The trade is that the container is privileged and mounts the Docker socket, and the newest tagged release is from December 2024.

**d3vilh/openvpn-ui** — Web User Interface for OpenVPN

- Repository: https://github.com/d3vilh/openvpn-ui
- Stars: 748 · Forks: 167
- Language: JavaScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/d3vilh-openvpn-ui

## Certificate lifecycle in the browser instead of at the openssl prompt

The problem is that running an OpenVPN server for a handful of remote users means constantly issuing, renewing and revoking client certificates, and the stock workflow for that is a sequence of EasyRSA commands that have to be typed correctly on the host. openvpn-ui moves that into a web interface. The feature list names the operations directly: it is easy to generate, download, renew, revoke, delete and view client certificates, and a client can be given a secret passphrase and a static IP address at the moment its certificate is generated. It also maintains the EasyRSA PKI infrastructure itself, with the init, build-ca, gen-dh, build-crl, gen-ta and revoke operations listed, and it can change the predefined EasyRSA variables, including certificate and CRL expiration time. The intended user is the operator of a small OpenVPN environment, which is what the README means when it describes the tool as quick to deploy and easy to use for small environments.

## It is a Go application with Beego, even though the repo lists JavaScript

The repository is worth reading carefully, because the metadata and the code disagree in a way that matters for anyone picking a base image or reading the source. The repository description lists JavaScript as the primary language, but the top level contains main.go, a go.mod, a go.sum, and directories named controllers, models, routers, lib and state, which is the layout of a Go web application. The go.mod confirms it. The module path is github.com/d3vilh/openvpn-ui, the Go directive is 1.26.5, and the direct dependencies are Beego v2.3.10 for the web framework, gosigar for system information, the openvpn-server-config package, go-ldap for directory integration, go-sqlite3 for the database, golang.org/x/oauth2 and google.golang.org/api for OAuth, and passlib for password hashing. The README's own infrastructure list names GoLang 1.21 and Beego 2.1 as the versions the container images were built with, which is behind what go.mod now requires.

## Server configuration and restarts happen through the same interface

Beyond certificates, the interface covers the day to day administration of the server itself. There is a status page showing server statistics and the list of connected clients, an easy way to preview the OpenVPN server logs, and the ability to restart both the OpenVPN server and the OpenVPN UI itself from the web interface. The OpenVPN server configuration can be changed through the web interface rather than by editing server.conf on the host and restarting. The server mode is not fixed: the README states that both tunnel, using dev tun, and bridge, using dev tap, server configurations are supported, which covers the two common reasons people pick OpenVPN over another VPN daemon. The two administration surfaces, a status view and a configuration editor, are what separate this from a script collection and turn it into something a non-specialist can be handed.

## Two user roles, and 2FA on the admin side

Access control is built in rather than bolted on. The feature list describes OpenVPN-UI users management where administrators have full access, while regular users are limited to certificates management, the logs and the status page. There is two factor authentication support for the UI itself, and the admin user and password can be passed into the container through environment variables, which is what lets a compose file bootstrap the first login. A separate project file, DUOAUTH, is not in this repository, but the go.mod dependency on go-ldap tells you that directory-backed authentication is implemented rather than merely planned. For a component that can mint credentials and read server logs, having distinct roles and a second factor on the administrator is the minimum sensible arrangement, and it is worth checking the 2FA setup before you expose the interface beyond your own network.

## The compose file shows the price of the design

The recommended deployment is two containers, the d3vilh/openvpn-server back end running OpenVPN and the openvpn-ui front end for managing it, but the README says it also works fine as a standalone application against a standalone OpenVPN server. The compose file published in the README is the clearest statement of the security posture, and the front-end service is configured like this:```yaml
    openvpn-ui:
       container_name: openvpn-ui
       image: d3vilh/openvpn-ui:latest
       environment:
           - OPENVPN_ADMIN_USERNAME={{ ovpnui_user }}
           - OPENVPN_ADMIN_PASSWORD={{ ovpnui_password }}
       privileged: true
       ports:
           - "8080:8080/tcp"
       volumes:
           - ./:/etc/openvpn
           - ./db:/opt/openvpn-ui/db
           - ./pki:/usr/share/easy-rsa/pki
           - /var/run/docker.sock:/var/run/docker.sock:ro
       restart: always
```Read that carefully. The container is privileged, the host directory is mounted over /etc/openvpn, the EasyRSA PKI lives in a mounted pki directory, the database in a db directory, and the Docker socket is mounted read-only so the UI can restart the server container it does not own. Privileged plus the Docker socket is a large amount of host access for a certificate management tool, and it is the first thing to scrutinise before deployment on a machine that holds anything else.

## The two container variant shares the PKI and passes subnet settings

The fuller compose file pairs the UI with the recommended server image and shows how the pieces are meant to fit together. The openvpn service exposes the UDP port, passes three subnet variables for the trusted, guest and home networks, mounts pki, clients, config, staticclients, log and the server configuration, and adds the NET_ADMIN capability. The UI service repeats the pattern from the single-container example with its own environment section. The subnet variables matter more than they look, because they define the address pools that the server will hand out, and the static IP assignment feature of the certificate generator only means something relative to those pools. The pairing also explains why the host directory mounts overlap: the PKI directory has to be the same directory for both containers or the UI would generate certificates the server cannot use.

## Where the project sits, and where it does not

The README positions openvpn-ui as one part of a family. The d3vilh/openvpn-server repository is the server counterpart, with its own Docker Hub image, and the openvpn-aws project packages OpenVPN and the UI for any cloud, VM or x86 bare metal server, including the scripts for automated installation. The Raspberry-gateway project covers ARM and Raspberry Pi deployments, adding Pi-Hole, Unbound, a torrent client and internet monitoring managed through Portainer. Images are published for AMD64 and ARM. The alternative to a web interface is running EasyRSA by hand or driving it from your own configuration management, which is a better fit when you have hundreds of clients and a pipeline already, and a worse fit when you have a dozen and one administrator. The boundary of this tool is that small to medium environment, and the risk is that the UI holds the keys to everything while running with host-level privileges.

## Conclusion

openvpn-ui suits an administrator of a small OpenVPN deployment who wants to issue and revoke client certificates from a browser instead of a shell, and who is comfortable running a privileged container with the Docker socket mounted. It does not suit a large site that already has its own provisioning pipeline, and it is a poor fit for anyone unwilling to run a container with host-level access. Before deploying, replace the example admin credentials in the compose file, decide whether the UI container and the OpenVPN server container share a host directory, and note that the last push to the repository was on 2026-07-30 while the newest tagged release is 0.9.5.6 from 2024-12-31.

## FAQ

### How do I deploy openvpn-ui?

The recommended setup is two Docker containers, the d3vilh/openvpn-server back end and the openvpn-ui front end, using the docker-compose-openvpnui.yml file from the openvpn-server repository. The README also says it works as a standalone application with a standalone OpenVPN server, and a docker-compose.yml example is included in the README itself.

### What languages and frameworks is openvpn-ui built on?

The source is Go, with Beego v2.3.10 as the web framework in go.mod, along with go-sqlite3, go-ldap, golang.org/x/oauth2 and passlib. The go.mod requires Go 1.26.5, while the README lists GoLang 1.21 and Beego 2.1 as the versions the container images use.

### Does openvpn-ui need privileged Docker access?

The compose file in the README sets privileged: true on the openvpn-ui service and mounts /var/run/docker.sock read-only so the interface can restart the server container, along with the host directory over /etc/openvpn. The openvpn service in the two-container example uses cap_add with NET_ADMIN instead.

### What can openvpn-ui do with client certificates?

It can generate, download, renew, revoke, delete and view client certificates, and it can assign a secret passphrase and a static IP to a client at generation time. It also maintains the EasyRSA PKI infrastructure, including init, build-ca, gen-dh, build-crl, gen-ta and revoke, and the predefined EasyRSA variables such as expiration times can be changed.

### What licence is openvpn-ui released under?

The project is released under the MIT Licence, with the licence text in the LICENSE file at the root of the repository. The newest tagged release is 0.9.5.6 from 2024-12-31, and the last push to the repository was on 2026-07-30.

## Sources

- [d3vilh/openvpn-ui on GitHub](https://github.com/d3vilh/openvpn-ui)
- [Issues](https://github.com/d3vilh/openvpn-ui/issues)
- [License: MIT](https://github.com/d3vilh/openvpn-ui/blob/main/LICENSE)
- [README](https://github.com/d3vilh/openvpn-ui/blob/main/README.md)
- [Releases](https://github.com/d3vilh/openvpn-ui/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/d3vilh-openvpn-ui
