Skip to content

hwdsl2/docker-openvpn

Repository files navigation

English | 简体中文 | 繁體中文 | Русский

OpenVPN Server on Docker

Build Status

A Docker image to run an OpenVPN server. Based on Alpine Linux with OpenVPN and EasyRSA. Designed to be simple, modern, and maintainable.

  • Automatically generates PKI, server certificates, and a client config on first start
  • Client management via a helper script (ovpn_manage)
  • Modern cipher suite: AES-128-GCM, SHA256, tls-crypt
  • IPv6 support when the server has a public IPv6 address (see requirements)
  • Persistent data via a Docker volume
  • Multi-arch: linux/amd64, linux/arm64, linux/arm/v7

Also available: Docker images for WireGuard, IPsec VPN, and Headscale.

Quick Start

Step 1. Start the OpenVPN server:

docker run \
    --name openvpn \
    --restart=always \
    -v openvpn-data:/etc/openvpn \
    -p 1194:1194/udp \
    -d --cap-add=NET_ADMIN \
    --device=/dev/net/tun \
    --sysctl net.ipv4.ip_forward=1 \
    --sysctl net.ipv6.conf.all.forwarding=1 \
    hwdsl2/openvpn-server

On first start, the server automatically generates a PKI, server certificate, TLS crypt key, and a client configuration named client.ovpn.

Step 2. Copy the client configuration to your local machine:

docker cp openvpn:/etc/openvpn/clients/client.ovpn .

Import client.ovpn into your OpenVPN client to connect.

Requirements

  • A Linux server with a public IP address or DNS name
  • Docker installed
  • VPN port open in your firewall (UDP 1194 by default, or your configured port/protocol)

Download

Get the trusted build from the Docker Hub registry:

docker pull hwdsl2/openvpn-server

Alternatively, you may download from Quay.io:

docker pull quay.io/hwdsl2/openvpn-server
docker image tag quay.io/hwdsl2/openvpn-server hwdsl2/openvpn-server

Supported platforms: linux/amd64, linux/arm64 and linux/arm/v7.

Update Docker Image

To update the Docker image and container, first download the latest version:

docker pull hwdsl2/openvpn-server

If the Docker image is already up to date, you should see:

Status: Image is up to date for hwdsl2/openvpn-server:latest

Otherwise, it will download the latest version. Remove and re-create the container using instructions from Quick Start. Your data is preserved in the openvpn-data volume.

Environment Variables

All variables are optional. If not set, secure defaults are used automatically.

This Docker image uses the following variables, that can be declared in an env file (see example):

Variable Description Default
VPN_DNS_NAME Fully qualified domain name (FQDN) of the server Auto-detected public IP
VPN_PUBLIC_IP Public IPv4 address of the server Auto-detected
VPN_PUBLIC_IP6 Public IPv6 address of the server Auto-detected
VPN_PROTO VPN protocol: udp or tcp udp
VPN_PORT VPN port (1–65535) 1194
VPN_CLIENT_NAME Name of the first client config generated client
VPN_DNS_SRV1 Primary DNS server pushed to clients 8.8.8.8
VPN_DNS_SRV2 Secondary DNS server pushed to clients 8.8.4.4

Note: In your env file, DO NOT put "" or '' around values, or add space around =. If you change VPN_PORT or VPN_PROTO, update the -p flag in the docker run command accordingly.

Example using an env file:

docker run \
    --name openvpn \
    --env-file ./vpn.env \
    --restart=always \
    -v openvpn-data:/etc/openvpn \
    -p 1194:1194/udp \
    -d --cap-add=NET_ADMIN \
    --device=/dev/net/tun \
    --sysctl net.ipv4.ip_forward=1 \
    --sysctl net.ipv6.conf.all.forwarding=1 \
    hwdsl2/openvpn-server

Client Management

Use docker exec to manage clients with the ovpn_manage helper script.

Add a new client:

docker exec openvpn ovpn_manage --addclient alice
docker cp openvpn:/etc/openvpn/clients/alice.ovpn .

Export a client config (prints to stdout):

docker exec openvpn ovpn_manage --exportclient alice > alice.ovpn

List clients:

docker exec openvpn ovpn_manage --listclients

Revoke a client (will prompt for confirmation):

docker exec -it openvpn ovpn_manage --revokeclient alice
# Or revoke without confirmation prompt:
docker exec openvpn ovpn_manage --revokeclient alice -y

Persistent Data

All server and client data is stored in the Docker volume (/etc/openvpn inside the container):

/etc/openvpn/
├── server/
│   ├── server.conf         # OpenVPN server configuration
│   ├── ca.crt              # CA certificate
│   ├── server.crt/key      # Server certificate and key
│   ├── tc.key              # TLS crypt key
│   ├── dh.pem              # DH parameters
│   ├── crl.pem             # Certificate revocation list
│   ├── client-common.txt   # Client config template
│   ├── ipp.txt             # IP pool persistence
│   └── easy-rsa/pki/       # Full PKI directory
└── clients/
    ├── client.ovpn         # First client config
    └── alice.ovpn          # Additional clients

Back up the Docker volume to preserve all keys and client configurations.

IPv6 Support

If the Docker host has a public (global unicast) IPv6 address and the requirements below are met, IPv6 support is automatically enabled when the container starts. No manual configuration is needed.

Requirements:

  • The Docker host must have a routable global unicast IPv6 address (starting with 2 or 3). Link-local (fe80::/10) addresses are not sufficient.
  • IPv6 must be enabled for the Docker container. See Enable IPv6 support in Docker.

To enable IPv6 for the Docker container, first enable IPv6 in the Docker daemon by adding the following to /etc/docker/daemon.json on the Docker host, then restart Docker:

{
  "ipv6": true,
  "fixed-cidr-v6": "fddd:1::/64"
}

After that, re-create the Docker container. To verify that IPv6 is working, connect to the VPN and check your IPv6 address, e.g. using test-ipv6.com.

Using docker-compose

cp vpn.env.example vpn.env
# Edit vpn.env if needed, then:
docker compose up -d
docker cp openvpn:/etc/openvpn/clients/client.ovpn .

Technical Details

  • Base image: alpine:3.23
  • OpenVPN: latest available from Alpine packages
  • EasyRSA: 3.2.6 (bundled at build time)
  • Cipher: AES-128-GCM
  • Auth: SHA256
  • Key exchange: tls-crypt (HMAC + encrypt)
  • DH parameters: pre-defined ffdhe2048 group (RFC 7919)
  • Client certificates: 10-year validity
  • VPN subnet: 10.8.0.0/24
  • IPv6 VPN subnet: fddd:1194:1194:1194::/64 (when server has IPv6)

License

Note: The software components inside the pre-built image (such as OpenVPN and EasyRSA) are under the respective licenses chosen by their respective copyright holders. As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within.

Copyright (C) 2026 Lin Song Creative Commons License
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.

This project is based in part on the work of Nyr and contributors, licensed under the MIT License.

About

Docker image to run an OpenVPN server, with automatic PKI setup and client management via a helper script. Based on Alpine Linux with OpenVPN and EasyRSA. Supports amd64, arm64 and arm/v7.

Topics

Resources

License

Stars

Watchers

Forks