Production-ready OpenVPN 2.7.7 server with EasyRSA & 6 management scripts
1.8K
OpenVPN server with automated certificate management, built from official source code.
openvpn.conf and PKI (CA, server cert, DH params, TLS-crypt key) are generated automatically on first startup, no manual init step.ovpn lifecycle - create-clients writes a ready-to-import .ovpn, revoke-clients deletes it, renew-clients rebuilds it with the new certgit clone https://github.com/Zaliyo/openvpn-docker-compose.git
cd openvpn-docker-compose
cp .env.example .env
Edit .env and set VPN_IP to this server's public IP or hostname -
every .ovpn file create-clients/renew-clients generates uses it
as the remote address. If you skip this, client creation still
works, but each generated .ovpn gets a placeholder you'll need to
edit by hand.
docker-compose up -d
That's it - no manual PKI initialization step is required. On
first boot the container automatically installs a default
openvpn.conf (if data/conf/openvpn.conf doesn't exist yet),
initializes the PKI (if data/conf/pki/ca.crt doesn't exist yet),
and starts the OpenVPN server. Watch it happen with:
docker-compose logs -f openvpn
First boot takes a minute or two (mostly Diffie-Hellman parameter generation). Every later restart just no-ops both checks and starts immediately - your PKI and config are never regenerated once they exist.
If initialization fails partway, fix the underlying issue (check the logs), then either restart the container to retry automatically, or re-run it directly:
docker-compose exec openvpn init-pki
docker-compose exec openvpn create-clients alice
cat users/alice.ovpn
.ovpn FileDownload the alice.ovpn file and import into:
All commands run via docker-compose exec openvpn <command>:
# PKI Management
init-pki # (Re-)run PKI init manually - not needed on a normal first boot
easyrsa <args> # Direct EasyRSA commands
# Client Management
create-clients alice bob # Create new clients, writes users/<name>.ovpn
list-clients # Show all clients with expiry
revoke-clients baduser # Revoke client certificate, removes users/baduser.ovpn
renew-clients alice # Renew expiring certificate, rewrites users/alice.ovpn with the new cert
# Server & Backup
status # Check server health and version
backup-pki # Backup certificates (encrypted)
Edit .env (in the docker-compose repo) to customize:
VPN_IP=1.2.3.4 # Your server's public IP or hostname
VPN_PORT=1194 # UDP port
DEBUG=0 # Set to 1 for verbose logs
docker scout cves currently shows gcc-12 present in the runtime image too; worth tracing which runtime package pulls it in as a dependency and removing it if it's not actually neededLD_LIBRARY_PATHThe base image (debian:12-slim) still ships a handful of packages with
open CVEs that this project doesn't control, since Debian hasn't
released fixes for most of them yet. Run docker scout cves zaliyo/openvpn:2.7.7 for the current, authoritative count - do not
treat any number here as up to date, since it changes with every base
image refresh. As of the last check:
pcre2 was out of date relative to Debian's own patched version
(10.42-1+deb12u1) - fixable by adding an apt-get upgrade step to
the Dockerfile before/after package install, not yet done.openssl/libssl3 (the Debian-packaged copy, distinct from the
source-compiled 3.6.4 above) still carries the unfixed
CVE-2026-75803 - it's a transitive dependency of another runtime
package, not something OpenVPN itself loads, but it is present on
disk and picked up by scanners.debian:12-slim..ovpn client bundles are kept in sync with certificate state:
created alongside the cert, deleted on revoke, rebuilt on renewView real-time logs:
docker-compose logs -f openvpn
Or check the log file:
cat data/logs/openvpn.log
docker-compose logs openvpn
docker-compose ps
sudo ufw allow 1194/udpVPN_IP in .env matches your server's public IPdocker-compose logs openvpnPKI initialization now runs automatically on first boot - if it fails partway, check the logs for the actual error, fix it, then either restart the container to retry automatically or re-run it directly:
docker-compose exec openvpn init-pki
sudo chown -R 65534:65534 data/conf
chmod 755 data/conf
# Backup with encryption
docker-compose exec openvpn backup-pki
# Restore from backup
docker cp openvpn-backup-20260915_120000.tar.gz openvpn:/tmp/
docker-compose exec openvpn restore-pki /tmp/openvpn-backup-20260915_120000.tar.gz
docker-compose exec openvpn status -v
Edit the OpenVPN config file:
nano data/conf/openvpn.conf
docker-compose restart openvpn
2.7.7, latestv2.7.7 (2026-09-15)
openvpn.conf install and PKI initialization.ovpn client bundle lifecycle kept consistent across create/revoke/renewFor full changelog, see CHANGELOG.md
Built with ❤️ for production deployments
Start your secure VPN today → Use docker-compose up -d to get started!
Content type
Image
Digest
sha256:d2ddd116a…
Size
50.2 MB
Last updated
about 15 hours ago
docker pull zaliyo/openvpn