## Summary
- Add native firewalld support for RHEL/Fedora/CentOS systems
- When firewalld is active, use `firewall-cmd --permanent` instead of
raw iptables
- Rules persist across `firewall-cmd --reload`
- Fall back to iptables when firewalld is not active
- Add `After=firewalld.service` to iptables systemd unit for safety
## Changes
**Install:** Detect firewalld, use `firewall-cmd` to add port,
masquerade, and rich rules. Fall back to iptables if inactive.
**Uninstall:** Detect which method was used and clean up accordingly.
**Tests:** Add `fedora-42-firewalld` CI test with firewalld enabled.
---
Closes https://github.com/angristan/openvpn-install/issues/356
Closes https://github.com/angristan/openvpn-install/pull/1200
Add support for revoking clients by setting the CLIENT environment
variable directly with the client name, in addition to the existing
CLIENTNUMBER support (from
https://github.com/angristan/openvpn-install/pull/1328)
This makes headless revocation more user-friendly as users no longer
need to know the client's index number.
Add a flag `NEW_CLIENT` so that the user can choose whether or not he
wishes to create a new user after installation.
It is specially useful on headless installations, when upgrading to a
different server, but keeping old credentials.
It does not change any defaults, so if no flag is passed, it still
creates the new user.
---------
Co-authored-by: Stanislas Lange <git@slange.me>
## Summary
- Add new "List existing users" option to management menu (option 2)
- Displays all client certificates with status (Valid/Revoked),
expiration date, and days remaining
- Reads expiry directly from certificate files using openssl for
accurate 4-digit year dates
- Output sorted by expiration date (oldest first)
- Updates test MENU_OPTION values to match new menu numbering
Example output:
```
=== Existing Clients ===
Found 2 certificate(s)
Name Status Expiry Remaining
---- ------ ------ ---------
user1 Valid 2035-12-11 3649 days
user2 Revoked unknown unknown
```
Closes#567Closes#563Closes#587
## Summary
- Replace deprecated `--genkey --secret` syntax with `--genkey secret`
for tls-crypt and tls-auth key generation
The OpenVPN source explicitly warns about this:
```
WARNING: Using --genkey --secret filename is DEPRECATED. Use --genkey secret filename instead.
```
Closes#1256
Close https://github.com/angristan/openvpn-install/issues/1280
Add support for a password protected user in headless mode
Fixes#389
---------
Co-authored-by: Siebren Kraak <siebren.kraak@secura.com>
Co-authored-by: Stanislas Lange <git@slange.me>
- Only cancel in-progress CI jobs for pull requests, not for master
branch pushes
- Ensures all master branch jobs run to completion while still saving CI
resources on PRs
## Summary
- Add support for OpenVPN's `tls-crypt-v2` feature (per-client TLS keys)
- Set `tls-crypt-v2` as the new recommended default
- Add CI tests for all 3 TLS key types
Closes#983Closes#758
Closes https://github.com/angristan/openvpn-install/pull/1257
## What is tls-crypt-v2?
Unlike `tls-crypt` (shared key), `tls-crypt-v2` generates unique keys
per client:
- **Better security**: Compromised client keys don't affect other
clients
- **Easier management**: Individual client key revocation without
regenerating server key
- **Scalability**: Better suited for large deployments
Requires OpenVPN 2.5+ (released 2020).
## Menu options
```
1) tls-crypt-v2 (recommended): Encrypts control channel, unique key per client
2) tls-crypt: Encrypts control channel, shared key for all clients
3) tls-auth: Authenticates control channel, no encryption
```
## Summary
This PR contains three related improvements:
### 1. Add `run_cmd_fatal` for critical operations
- New helper function that wraps `run_cmd` and exits on failure
- Converts critical operations (package installs, PKI setup, certificate
generation) to fail fast
- Non-critical operations (systemctl, cleanup) still use `run_cmd`
- Password-protected client certs run directly to preserve interactive
prompt
### 2. Fix Fedora installation
- Skip Copr repository setup since Fedora already ships OpenVPN 2.6.x
- Simplifies installation and removes external repository dependency
### 3. Improve CI test reliability
- Fail fast when `openvpn-test.service` fails during startup
- Add `journalctl` output to error diagnostics
- Display service status in wait loop
- Increase VPN gateway ping count from 3 to 10 for stability
On Arch Linux, the script uses `pacman -Syu` which performs a full
system upgrade. If a user's system is out of date and has pending kernel
updates:
1. Script runs `pacman -Syu` to install OpenVPN
2. Kernel gets upgraded along with other packages
3. The TUN module for the **new** kernel isn't loaded (old kernel still
running)
4. OpenVPN fails to start because TUN is unavailable
5. User has to reboot anyway, but now they're confused about why it
broke
So we check preventively now, and ask them to upgrade & reboot before
running the script
<img width="1342" height="488" alt="image"
src="https://github.com/user-attachments/assets/e9646737-eaf4-4035-b247-20e8f2daea60"
/>
- Replace the `sed` hack that disabled `systemctl` commands with proper
systemd support in Docker containers
- This allows testing the actual `systemctl` commands used by the
install script
- No more manual workarounds for starting OpenVPN/Unbound services
- Increase DNS retry count from 5 to 10 for improved test reliability
when Unbound needs more time to initialize
- Refactor retry loop to use `seq` with a `DNS_MAX_RETRIES` to be
cleaner
## Summary
- Add `tar` and DNS utilities (`dnsutils`/`bind-utils`/`bind`) to all
supported distros
- Ensures the script works reliably on minimal system images where these
tools may not be pre-installed
## Changes by distro
| Distro | Packages added |
|--------|----------------|
| debian/ubuntu | `tar`, `dnsutils` |
| centos | `bind-utils` |
| oracle | `bind-utils` |
| amzn2023 | `tar`, `bind-utils` |
| fedora | `tar`, `bind-utils` |
| opensuse | `tar`, `bind-utils` |
| arch | `tar`, `bind` |
## Why these packages?
- **tar**: Required for extracting Easy-RSA `.tgz` archive
- **dnsutils/bind-utils/bind**: Provides `dig` command used as fallback
for public IP detection
## Summary
Migrates OpenVPN configuration to use the modern OpenVPN 2.4+ directory
structure and improves compatibility across different Linux
distributions.
Close https://github.com/angristan/openvpn-install/issues/1307, close
https://github.com/angristan/openvpn-install/issues/788, close
https://github.com/angristan/openvpn-install/issues/605, close
https://github.com/angristan/openvpn-install/pull/653, close
https://github.com/angristan/openvpn-install/issues/1214
### Directory Structure Changes
- All server files now in `/etc/openvpn/server/` instead of
`/etc/openvpn/`
- Uses `openvpn-server@server.service` consistently across all distros
- `server.conf` uses relative paths for portability
### Distro-Specific User/Group Handling
Different distros configure OpenVPN differently:
| Distro | User | Group | systemd handles user? |
|--------|------|-------|----------------------|
| Debian/Ubuntu | nobody | nogroup | No |
| Fedora/RHEL/Amazon | openvpn | openvpn | No |
| Arch | openvpn | network | **Yes** (via `User=` in service) |
The script now:
1. Detects if an `openvpn` user exists and uses appropriate group
2. Checks if systemd service already has `User=` directive
3. Skips `user`/`group` in config when systemd handles it (avoids
"double privilege drop" error on Arch)
4. Sets file ownership with `chown -R` for non-root OpenVPN users
### Other Changes
- Updated FAQ.md with new paths
- Added systemd service file validation in tests
- Added CRL reload verification in tests
## Summary
- Add `data-ciphers` directive alongside `ncp-ciphers` for
future-proofing
- Server config now emits both `data-ciphers` and `ncp-ciphers`
- Client config adds `ignore-unknown-option data-ciphers`,
`data-ciphers`, and `ncp-ciphers` for full backward compatibility with
OpenVPN 2.4 clients
## Context
The `ncp-ciphers` option is a legacy alias of `data-ciphers` that is
still accepted but deprecated in OpenVPN 2.5+. This change aligns with
modern naming conventions while maintaining compatibility with older 2.4
clients.
Modernise the Security and Encryption section to reflect OpenVPN's
improved defaults over the years.
- Add version-by-version changelog of security improvements (2.4, 2.5,
2.6)
- Add `[!NOTE]` callouts for default changes in subsections
- Update Easy-RSA link (v3.0.7 → v3.2.2)
## Summary
- Add `remote-cert-tls client` directive to server config to ensure only
certificates with "TLS Web Client Authentication" EKU can connect
- Document the feature in the Security and Encryption section of
README.md
## Summary
- Only add `ifconfig-pool-persist` to server.conf when `MULTI_CLIENT !=
y`
- Add note in the installation prompt about this limitation
- Update README to mention the trade-off
First reported in
https://github.com/angristan/openvpn-install/issues/440#issuecomment-2987417197
## Background
`ifconfig-pool-persist` is incompatible with `duplicate-cn`. When
`duplicate-cn` is enabled, OpenVPN bypasses common name matching in the
IP pool allocation, making the persistence file ineffective.
From [OpenVPN
source](https://github.com/OpenVPN/openvpn/blob/e5ff8247/src/openvpn/init.c#L3608-L3610):
```c
if (o->duplicate_cn && o->ifconfig_pool_persist_filename)
{
msg(M_WARN, "WARNING: --ifconfig-pool-persist will not work with --duplicate-cn");
}
```
Previously, the script always added `ifconfig-pool-persist ipp.txt`
regardless of whether `duplicate-cn` was enabled via `MULTI_CLIENT=y`.
<!---
❗️ Please read ❗️
➡️ Please make sure you've followed the guidelines:
https://github.com/angristan/openvpn-install#contributing✅ Please make sure your changes are tested and working
🗣️ Please avoid large PRs, and discuss changes in a GitHub issue first
✋ If the changes are too big and not in line with the project, they will
probably be rejected. Remember that this script is meant to be simple
and easy to use.
--->
---------
Co-authored-by: Stanislas Lange <git@slange.me>
## Summary
- Add version 10 support for CentOS Stream, Rocky Linux, AlmaLinux, and
Oracle Linux
- Consolidate version check logic into a single check for all RHEL-based
distributions
- Fix Rocky Linux Docker image names to `rockylinux/rockylinux:tag`
- Increase Easy-RSA download curl retry from 3 to 5
- Fail early if EPEL/Copr repository setup fails
- Fix Oracle Linux EPEL package name (`oracle-epel-release-el*` instead
of `epel-release`)
## Changes
### `openvpn-install.sh`
- Combine version checks for CentOS/Rocky/AlmaLinux and Oracle Linux
into one
- Update error message to list supported distributions
- Change Easy-RSA download `--retry 3` to `--retry 5`
- Add `|| log_fatal` to EPEL and Copr setup commands to fail early on
errors
- Use `oracle-epel-release-el{8,9,10}` for Oracle Linux instead of
`epel-release`
### `.github/workflows/docker-test.yml`
- Add CentOS Stream 10 (`quay.io/centos/centos:stream10`)
- Add Rocky Linux 10 (`rockylinux/rockylinux:10`)
- Add AlmaLinux 10 (`almalinux:10`)
- Add Oracle Linux 10 (`oraclelinux:10`)
- Fix Rocky Linux image names from `rockylinux:X` to
`rockylinux/rockylinux:X`
## Test plan
- [ ] CI passes for existing distributions
- [ ] CI passes for new version 10 distributions (where images are
available)
## Summary
- Add end-to-end tests for certificate revocation functionality
- Test that a revoked client certificate cannot connect to the VPN
- Test that a new certificate can be created with the same name as a
revoked one (validating the fix from #1185)
- Test that the new certificate can successfully connect
## Test Flow
1. **Initial connectivity tests** - existing tests pass
2. **Certificate revocation test**:
- Create a new client `revoketest`
- Connect with the certificate (verifies it works)
- Disconnect the client
- Revoke the certificate via the install script
- Try to reconnect with revoked cert (verifies connection is rejected)
3. **Reuse revoked name test**:
- Create a new certificate with the same name `revoketest`
- Verify both revoked and valid entries exist in `index.txt`
- Connect with the new certificate (verifies it works)
## Changes
| File | Changes |
|------|---------|
| `test/server-entrypoint.sh` | Start OpenVPN in background, add
revocation test orchestration |
| `test/client-entrypoint.sh` | Add revocation test phases with signal
file coordination |
| `docker-compose.yml` | Remove read-only restriction on shared volume
for client |
| `Makefile` | Increase timeout from 60 to 180 iterations |
| `.github/workflows/docker-test.yml` | Increase timeouts, fix shared
volume |
The previous check using `pgrep -x openvpn` was matching transient
openvpn processes like `openvpn --genkey` that run during installation,
causing false positives. This led to race conditions where the CI
thought the server was running when it was actually still installing.
Use `pgrep -f "openvpn.*server.conf"` to specifically match the actual
OpenVPN server process running with the server configuration.
Add step to display the install script log file (openvpn-install.log)
which includes timestamps and all installation activity.
This makes debugging CI failures easier by providing detailed logs
directly in the workflow output.
- Replace `wget` with `curl` for downloading Easy-RSA
- Remove `wget` from package dependencies across all distributions
- Ensure `curl` and `ca-certificates` are installed on all distributions
- Add `--retry 3` for automatic retries on transient network failures
I know I’m setting up open VPN because google gave me this page, but I
wasn’t sure if I should run this script on my Amazon Linux 2 server or
my MacBook Pro client for a hot minute.
<!---
❗️ Please read ❗️
➡️ Please make sure you've followed the guidelines:
https://github.com/angristan/openvpn-install#contributing✅ Please make sure your changes are tested and working
🗣️ Please avoid large PRs, and discuss changes in a GitHub issue first
✋ If the changes are too big and not in line with the project, they will
probably be rejected. Remember that this script is meant to be simple
and easy to use.
--->
---------
Co-authored-by: Stanislas <github@slange.me>
- Add a new "Why OpenVPN?" section explaining when OpenVPN is preferable
over WireGuard
- Move the wireguard-install link from the intro to this new section
- Add detection and logging for OpenVPN Data Channel Offload (DCO)
support during installation
- DCO is a kernel acceleration feature (merged into Linux 6.16) that
improves VPN performance
- Add DCO documentation to README
- Commits made with `GITHUB_TOKEN` don't trigger workflows
- Using a PAT allows the hash update commit to trigger CI checks
- Fixes the issue where PR #1335 didn't have CI triggered after the hash
update
## Summary
- Add Renovate configuration to automatically track Easy-RSA releases
- Add GitHub Action to auto-update SHA256 hash on Renovate PRs
## How it works
1. **Renovate** detects a new Easy-RSA release → creates PR updating
`EASYRSA_VERSION`
2. **GitHub Action** triggers on the PR → downloads tarball → computes
SHA256 → commits fix
3. PR is ready to merge with both version and hash updated
---
I intentionally updated to the second-to-last version in
bda450948a
to test if this works.
## Summary
- Remove Amazon Linux 2 support from the installer
- Amazon Linux 2023 remains fully supported
## Motivation
Amazon Linux 2 is reaching EOL.
Additionally, Amazon Linux 2 ships with **OpenSSL 1.0.2k** (from 2017)
which is incompatible with Easy-RSA 3.2.x. The newer Easy-RSA versions
use `openssl x509 -ext` which doesn't exist in OpenSSL 1.0.x, causing
certificate generation to fail.
This blocks our ability to upgrade Easy-RSA:
bda450948a
## Changes
- Updated OS detection to reject Amazon Linux 2 with a clear message
- Removed Amazon Linux 2 specific code paths (EPEL installation, yum
commands)
- Removed from CI test matrix
- Updated README supported distributions table
- Updated Makefile test targets
- Also, add Amazon Linux 2023 Unbound handling
## Summary
- Add `CHACHA20-POLY1305` as a data channel cipher option
- Add `ECDHE-*-CHACHA20-POLY1305` control channel cipher options
- Add version check (requires OpenVPN 2.5+)
- Update README documentation
ChaCha20-Poly1305 is particularly useful on devices without hardware AES
acceleration (AES-NI), such as ARM-based devices (Raspberry Pi, etc.)
and older CPUs, where it can provide better performance than AES.
Closes#1244Closes#190