Commit Graph
100 Commits
Author SHA1 Message Date
StanislasandGitHub 63eff762dd fix: use run_cmd_fatal for package list updates (#1423)
## Summary
- Changed `apt-get update` commands from `run_cmd` to `run_cmd_fatal`
- Package list updates are critical operations that should fail the
installation if they fail
- Affects 3 locations: initial update, post-repo-add update, and removal
cleanup
2025-12-15 12:36:18 +01:00
StanislasandGitHub 04f7178c80 feat: add TLS 1.3 support, replace ecdh-curve with tls-groups (#1421)
## Summary

- Add TLS 1.3 support with `--tls-version-min` and `--tls-ciphersuites`
- Replace deprecated `ecdh-curve` with `tls-groups`
- Remove traditional DH support (OpenVPN 2.7 defaults to ECDH)

## New options

| Option | Default |
|--------|---------|
| `--tls-version-min` | `1.2` |
| `--tls-ciphersuites` |
`TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256`
|
| `--tls-groups` | `X25519:prime256v1:secp384r1:secp521r1` |

## Removed

- `--dh-type`, `--dh-bits`, `--dh-curve`
- DH parameter generation

Closes https://github.com/angristan/openvpn-install/issues/1231
Closes https://github.com/angristan/openvpn-install/issues/637
Closes https://github.com/angristan/openvpn-install/issues/1362
2025-12-15 12:13:03 +01:00
StanislasandGitHub 2e0605e2eb fix: validate client name length to prevent invalid certificates (#1420)
## Summary
- Add `is_valid_client_name()` helper and `validate_client_name()`
function to enforce client name constraints
- Reject client names longer than 64 characters (OpenSSL CN limit)
- Apply validation at all entry points: interactive prompt, `client add`
CLI, and `--client` install option

## Problem
Client names longer than 64 bytes cause Easy-RSA/OpenSSL to silently
truncate or reject Common Names, resulting in `.ovpn` files with empty
`<cert>/<key>` sections. Users (especially in headless/automated
deployments) would see the script complete successfully but get
non-functional output.

Fixes #1306
2025-12-15 11:24:01 +01:00
8375af5452 feat: add configurable MTU support (#1417)
## Summary
- Add `--mtu <size>` CLI option to configure tunnel MTU (valid range:
576-65535)
- Add interactive prompt with user-friendly explanation for
non-technical users
- Write `tun-mtu` to server.conf and client template when custom value
is set
- OpenVPN auto-calculates MSSFIX based on the MTU value (no separate
option needed)

## Use cases
- PPPoE connections (typically need MTU ~1492)
- Mobile/cellular networks with variable MTU
- Networks with connectivity issues due to fragmentation

## Usage
```bash
# CLI mode
./openvpn-install.sh install --mtu 1400

# Interactive mode prompts with explanation:
# "MTU controls the maximum packet size. Lower values can help
#  with connectivity issues on some networks (e.g., PPPoE, mobile)."
```

Close https://github.com/angristan/openvpn-install/pull/1300

Co-authored-by: Fabian Druschke <fdruschke@outlook.com>
2025-12-15 10:53:15 +01:00
StanislasandGitHub 15ca74639c feat: remove compression support (#1418)
## Summary

- Remove compression support from the script (CLI option, interactive
prompts, config generation)
- Compression is unsafe due to the VORACLE attack and OpenVPN is
deprecating it
- Simplify DCO compatibility check (no longer needs compression
condition)

Closes https://github.com/angristan/openvpn-install/issues/872
2025-12-15 10:04:02 +01:00
StanislasandGitHub 898489f3c9 fix: exit non-zero when client name exists (#1407)
Fixes https://github.com/angristan/openvpn-install/issues/1194
2025-12-15 09:57:52 +01:00
StanislasandGitHub ec3e80ac16 feat: add CLI interface with subcommands (#1398)
Replace environment variable-based configuration with a proper CLI
interface using subcommands and flags.

### Commands

```
openvpn-install <command> [options]

Commands:
  install       Install and configure OpenVPN server
  uninstall     Remove OpenVPN server
  client        Manage client certificates (add/list/revoke/renew)
  server        Server management (status/renew)
  interactive   Launch interactive menu
```

### Highlights

- **No args → help**: Running without arguments shows help instead of
interactive menu
- **JSON output**: `client list` and `server status` support `--format
json`
- **25+ install flags**: Network, DNS, security, and client options
- **Interactive mode preserved**: `install --interactive` or
`interactive` command

### Breaking Changes

Environment variables (`AUTO_INSTALL`, `MENU_OPTION`, `CLIENT`, etc.)
are no longer supported. Use CLI flags instead.

```bash
# Before
MENU_OPTION=1 CLIENT=foo PASS=1 ./openvpn-install.sh

# After
./openvpn-install.sh client add foo
```


Closes https://github.com/angristan/openvpn-install/issues/1202
2025-12-14 22:08:44 +01:00
StanislasandGitHub 648fe1ee0b feat: add option to list connected clients (#1396)
## Summary
- Add new menu option "3) List connected clients" to show currently
connected VPN clients
- Parses `/var/log/openvpn/status.log` and displays client name, real
IP, VPN IP, connection time, and transfer stats
- Human-readable byte formatting (K/M/G)

## Example output
```
   Name                 Real Address           VPN IP           Connected Since      Transfer
   ----                 ------------           ------           ---------------      --------
   stan                 123.45.211.11:28291    10.8.0.2         2025-12-14 10:13:22  ↓7.3M ↑123.5M
```

Closes https://github.com/angristan/openvpn-install/pull/863
2025-12-14 13:04:39 +01:00
e9deb4b8ab feat: add configurable VPN subnet (#1394)
Allow users to customize the VPN subnet during installation instead of
using the hardcoded `10.8.0.0/24`.

- Add subnet prompt during interactive installation (default or custom)
- Add `VPN_SUBNET` environment variable for headless installs
- Validate RFC1918 /24 networks (e.g., `10.9.0.0`, `172.16.0.0`,
`192.168.1.0`)

Closes https://github.com/angristan/openvpn-install/issues/153
Closes https://github.com/angristan/openvpn-install/pull/550
Closes https://github.com/angristan/openvpn-install/pull/1150
Closes https://github.com/angristan/openvpn-install/pull/952
Closes https://github.com/angristan/openvpn-install/pull/551

Co-authored-by: browningluke <lrbrowning6@gmail.com>
2025-12-14 10:54:52 +01:00
StanislasandGitHub cb0ef7b1c2 fix: use /etc/openvpn/server/ for tls-crypt-v2 temp files (#1393)
## Summary

- Fix tls-crypt-v2 client key generation failing on Ubuntu 25.04+ with
"Permission denied"
- Add Ubuntu 25.10 to CI test matrix

## Root Cause

Ubuntu 25.04 introduced an AppArmor profile for openvpn
(`/etc/apparmor.d/openvpn`) that restricts where the binary can write.
The allowed paths are:
- `/etc/openvpn/{,**}`
- `@{HOME}/**` (owner only)

The script was using `mktemp` which creates files in `/tmp`, causing the
error:
```
Cannot open file '/tmp/tmp.XXX' for write: Permission denied (errno=13)
```

## Fix

Changed the temp file location from `/tmp` to `/etc/openvpn/server/`:
```bash
# Before
tls_crypt_v2_tmpfile=$(mktemp)

# After
tls_crypt_v2_tmpfile=$(mktemp /etc/openvpn/server/tls-crypt-v2-client.XXXXXX)
```

Fixes #1391
2025-12-14 00:23:43 +01:00
StanislasandGitHub 8ea2d1b5b2 feat: add native nftables support (#1389)
- Add nftables as a third firewall backend option alongside firewalld
and iptables
- Detection priority: firewalld → nftables → iptables (legacy fallback)
- Uses dedicated `openvpn` and `openvpn-nat` tables for clean isolation
- Integrates with native `nftables.service` via include in
`/etc/nftables.conf`


Closes https://github.com/angristan/openvpn-install/issues/530
2025-12-14 00:03:29 +01:00
StanislasandGitHub a220d3a689 fix: improve CLIENT_FILEPATH handling and reduce code duplication (#1390)
## Summary

Follow-up improvements to #962:

- **Fix `getClientOwner()` edge case**: Now verifies the user actually
exists via `id` command before attempting to set ownership. Previously
only checked if `/home/$client` directory existed, which could fail if
the directory exists but the user doesn't.

- **Add directory creation for custom paths**: When `CLIENT_FILEPATH`
points to a non-existent directory, the script now creates it
automatically with `mkdir -p`.

- **Reduce code duplication**: Extract the repeated filepath/permission
logic from `newClient()` and `renewClient()` into a new
`writeClientConfig()` helper function, removing ~30 lines of duplicated
code.
2025-12-13 23:31:52 +01:00
StanislasandGitHub d8aa625639 feat: add native firewalld support (#1388)
## 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
2025-12-13 20:49:40 +01:00
StanislasandGitHub 9175c2c221 feat: support headless client revocation by name (#1387)
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.
2025-12-13 20:18:07 +01:00
StanislasandGitHub 0f2bd04447 feat: change default DNS resolver to Cloudflare (#1385)
- Change default DNS resolver from AdGuard DNS to Cloudflare (1.1.1.1)
- Applies to both interactive mode and AUTO_INSTALL mode
2025-12-13 19:32:07 +01:00
StanislasandGitHub 190e49ec33 feat: add list clients menu option (#1382)
## 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 #567
Closes #563
Closes #587
2025-12-13 19:17:30 +01:00
StanislasandGitHub 90f2313ff3 fix: use non-deprecated --genkey syntax for tls-crypt and tls-auth (#1383)
## 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
2025-12-13 18:59:40 +01:00
StanislasandGitHub 75ea8ef1c1 ci: only cancel in-progress jobs for pull requests (#1378)
- 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
2025-12-13 15:14:15 +01:00
Stanislas Lange 991c403d78 chore: fix AGENTS.md linting (GitHub/Docker capitalization) 2025-12-13 14:56:23 +01:00
Stanislas Lange 3afccf0351 Add AGENTS.md 2025-12-13 14:34:09 +01:00
StanislasandGitHub 3561d13389 feat: add tls-crypt-v2 support with per-client keys (#1377)
## 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 #983
Closes #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
```
2025-12-13 14:32:38 +01:00
StanislasandGitHub 2c53bc0f83 feat: add run_cmd_fatal, fix Fedora, improve CI (#1369)
## 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
2025-12-13 13:31:54 +01:00
StanislasandGitHub e7aa52b51f fix(arch): detect pending kernel upgrades before installation (#1372)
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"
/>
2025-12-13 10:55:36 +01:00
StanislasandGitHub 9e1bb4b175 feat: enable proper systemd support in Docker tests (#1373)
- 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
2025-12-13 01:14:54 +01:00
StanislasandGitHub 236e77af68 feat: add logging for system checks in initialCheck (#1371)
Add debug and info logging to initialCheck for better troubleshooting
visibility.
2025-12-12 23:47:09 +01:00
StanislasandGitHub 179cbc0c25 fix: increase DNS test retries and use seq for loop (#1370)
- 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
2025-12-12 23:38:12 +01:00
StanislasandGitHub 408d577461 feat: add missing dependencies for all supported distros (#1368)
## 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
2025-12-12 23:17:12 +01:00
StanislasandGitHub 44c995df8e feat: migrate to OpenVPN 2.4+ directory structure and improve distro compatibility (#1364)
## 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
2025-12-12 22:09:18 +01:00
StanislasandGitHub 3bc52d245b feat: use modern data-ciphers naming while maintaining 2.4 compatibility (#1363)
## 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.
2025-12-12 10:23:36 +01:00
StanislasandGitHub 693b4c31fc docs: update Security and Encryption section for modern OpenVPN (#1360)
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)
2025-12-12 01:12:30 +01:00
StanislasandGitHub 79b2763514 feat: add remote-cert-tls client to server configuration (#1359)
## 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
2025-12-12 00:47:10 +01:00
StanislasandGitHub 04f2996c79 fix: disable ifconfig-pool-persist when duplicate-cn is enabled (#1354)
## 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`.
2025-12-12 00:04:51 +01:00
StanislasandGitHub 4b00f44e8e feat: add version 10 support for RHEL-based distributions (#1346)
## 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)
2025-12-11 20:22:00 +01:00
StanislasandGitHub 0d4d2229f4 test: add e2e tests for certificate revocation (#1345)
## 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 |
2025-12-11 18:22:16 +01:00
Stanislas LangeandStanislas 690414a56e ci: update Fedora versions to 42 and 43 2025-12-11 17:21:48 +01:00
Stanislas LangeandStanislas d9e11822db fix: use pgrep -f to detect OpenVPN server, not transient processes
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.
2025-12-11 17:21:48 +01:00
Stanislas LangeandStanislas 6cca56f5b5 ci: add install script log output in docker-test workflow
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.
2025-12-11 17:21:48 +01:00
StanislasandGitHub 65f4885c36 refactor: replace wget with curl (#1343)
- 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
2025-12-11 17:04:44 +01:00
Stanislas Lange 599d122113 fix: use pgrep -x to accurately check for OpenVPN process in docker-test workflow 2025-12-11 16:26:45 +01:00
Stanislas Lange e06329c770 docs: update README to include Amazon Linux in supported distributions 2025-12-11 13:49:05 +01:00
StanislasandGitHub 0f324ef3b9 docs: add "Why OpenVPN?" section to README (#1341)
- 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
2025-12-11 13:45:53 +01:00
2374e4e81c Refactor Unbound setup and add E2E tests (#1340)
Refactor Unbound DNS installation to use modern `conf.d` pattern and add
E2E testing.

**Changes:**
- Unified Unbound config across all distros using
`/etc/unbound/unbound.conf.d/openvpn.conf`
- Added startup validation with retry logic
- Added `ip-freebind` to allow binding before tun interface exists
- E2E tests now verify Unbound DNS resolution from VPN clients

**Testing:**
- Server: verifies config creation, interface binding, security options
- Client: verifies DNS resolution through Unbound (10.8.0.1)

---

Closes https://github.com/angristan/openvpn-install/issues/602 Closes
https://github.com/angristan/openvpn-install/pull/604 Closes
https://github.com/angristan/openvpn-install/issues/1189

Co-authored-by: Henry N <henrynmail-github@yahoo.de>
2025-12-11 13:14:56 +01:00
StanislasandGitHub 2ecd4bd6e4 feat: add Data Channel Offload (DCO) availability check (#1331)
- 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
2025-12-10 18:53:45 +01:00
Stanislas Lange 5d9687f8b0 style: format renovate.json with prettier 2025-12-10 18:32:03 +01:00
StanislasandGitHub ba1d0419a8 fix: use PAT to trigger CI after hash update (#1337)
- 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
2025-12-10 18:23:58 +01:00
Stanislas Lange a6154c2653 Disable renovate check for disabled workflow 2025-12-10 18:14:57 +01:00
Stanislas Lange 2f24d2aec7 Remove Dependabot configuration 2025-12-10 18:14:01 +01:00
StanislasandGitHub a4c51f9bf9 ci: add Renovate for Easy-RSA version updates (#1333)
## 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
https://github.com/angristan/openvpn-install/commit/bda450948a933224f4f779a24a44c6279e1574a1
to test if this works.
2025-12-10 18:08:54 +01:00
StanislasandGitHub b9a1650027 feat: drop Amazon Linux 2 support (#1332)
## 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:
https://github.com/angristan/openvpn-install/commit/bda450948a933224f4f779a24a44c6279e1574a1

## 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
2025-12-10 17:54:00 +01:00
Stanislas Lange bda450948a feat: update EasyRSA version and revoke command 2025-12-10 16:58:35 +01:00
StanislasandGitHub c0fcf91972 feat: add ChaCha20-Poly1305 cipher support (#1330)
## 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 #1244 Closes #190
2025-12-10 00:11:25 +01:00
StanislasandGitHub ffcffac061 refactor: improve certificate duration variable naming (#1329)
## Summary

- Rename constants to `DEFAULT_CERT_VALIDITY_DURATION_DAYS` and
`DEFAULT_CRL_VALIDITY_DURATION_DAYS` for clarity
- Replace all hardcoded `3650` values with the constants
- Split `DAYS_VALID` into `CLIENT_CERT_DURATION_DAYS` and
`SERVER_CERT_DURATION_DAYS` for more granular control over client vs
server certificate validity
- Increase CRL validity to 15 years (5475 days) to provide a 5-year
safety buffer over the default 10-year certificate validity
- Update README with new headless install variables

## Breaking changes

- `DAYS_VALID` environment variable is replaced by
`CLIENT_CERT_DURATION_DAYS` and `SERVER_CERT_DURATION_DAYS`
2025-12-09 23:33:57 +01:00
Stanislas Lange f9a544104e docs: add missing headless variables to README
Add MULTI_CLIENT and DAYS_VALID to the documented headless install
variables, matching what the script actually supports.
2025-12-09 21:55:36 +01:00
StanislasandGitHub 6b09270347 feat: add certificate renewal functionality (#1328)
## Summary

- Add certificate renewal for both client and server certificates
- Allow custom validity period during renewal (prompts user, defaults to
3650 days)
- Show expiry info inline in menus (e.g., "Renew the server certificate
(expires in 3542 days)")
- Regenerate `.ovpn` files after client renewal
- Restart OpenVPN service after server renewal
- Extract reusable helper functions to reduce code duplication
- Add robust input validation and error handling

## New menu option

```
What do you want to do?
   1) Add a new user
   2) Revoke existing user
   3) Renew certificate        ← NEW
   4) Remove OpenVPN
   5) Exit
```

## Renewal submenu

```
What do you want to renew?
   1) Renew a client certificate
   2) Renew the server certificate (expires in 3542 days)
   3) Back to main menu
```

Client list shows expiry for each:
```
Select the existing client certificate you want to renew
     1) alice (expires in 3542 days)
     2) bob (expires in 30 days)
     3) charlie (EXPIRED 5 days ago)
```

## Helper functions added

Extracted common code into reusable functions:
- `getHomeDir()` - home directory detection
- `regenerateCRL()` - CRL regeneration after cert changes
- `generateClientConfig()` - .ovpn file generation  
- `selectClient()` - client listing with optional expiry display
- `getDaysUntilExpiry()` - certificate expiry calculation
- `formatExpiry()` - human-readable expiry formatting

## Test plan

- [x] Client certificate renewal tested in Docker CI
- [x] Server certificate renewal tested in Docker CI
- [x] Certificate validity verified after renewal (~3650 days)
- [x] VPN connectivity tested with renewed certificate

Closes #974 #1002 #1228 #1060
2025-12-09 21:49:19 +01:00
Stanislas Lange fb2041d9bb Improve command logging in run_cmd function 2025-12-09 21:41:08 +01:00
StanislasandGitHub 66890fb5d3 ci: prevent duplicate workflow runs (#1324)
## Summary
- Restrict `push` trigger to `master` branch only (feature branch pushes
won't trigger CI)
- Add concurrency groups to cancel redundant runs when new commits are
pushed
- Works correctly with fork PRs using standard `pull_request` event
2025-12-09 19:47:02 +01:00
StanislasandGitHub 8bd0c73f8f Use official OpenVPN repositories for latest stable versions (#1323)
## Summary

- Install OpenVPN from official upstream repositories instead of
distribution packages
- Gets the latest stable releases with security fixes and new features
- Properly cleans up repos and GPG keys on uninstall

## Repository sources

| OS | Repository |
|---|---|
| Debian/Ubuntu | `build.openvpn.net/debian/openvpn/stable` |
| CentOS/Oracle/Fedora | Fedora Copr `@OpenVPN/openvpn-release-2.6` |
| Amazon Linux/Arch | Distribution packages (no official repo available)
|

## Changes

- Add `installOpenVPNRepo()` function to configure official repos before
package installation
- Remove duplicate package installations between repo setup and install
functions
- Clean up repos and GPG keys during uninstall
- Standardize `log_success` (`[OK]`) for major milestones only


---

Close https://github.com/angristan/openvpn-install/pull/1294
2025-12-09 19:45:56 +01:00
Stanislas Lange b23517dbb0 Fix MULTI_CLIENT prompt blocking auto-install mode
The duplicate-cn feature added an interactive prompt that wasn't
following the auto-install pattern, causing the script to hang
when running with AUTO_INSTALL=y.
2025-12-09 18:30:57 +01:00
Stanislas Lange cd0fc55bf7 docs: add duplicate-cn feature to README 2025-12-09 18:15:54 +01:00
Stanislas Lange 8a133b7bed ci: run Docker e2e tests on pull requests 2025-12-09 18:06:53 +01:00
StanislasandGitHub 004fbb477a Add structured logging system with color-coded output and file logging (#1321)
## Summary
- Add comprehensive logging system with color-coded log levels ([INFO],
[WARN], [ERROR], [OK])
- Wrap all command executions with `run_cmd()` to capture output and
prevent leaks to stdout
- Add file logging with timestamps (default: `openvpn-install.log`)
- Suppress interactive prompts in auto-install mode for cleaner
CI/scripted usage
- Show log file location hint on errors for easier debugging

## Changes
- **openvpn-install.sh**: New logging functions (`log_info`, `log_warn`,
`log_error`, `log_fatal`, `log_success`, `log_prompt`, `log_header`,
`log_menu`, `run_cmd`), all `echo` statements converted to use logging
functions
- **test/validate-output.sh**: New E2E validator that ensures all script
output uses proper log formatting (catches raw echo leaks)
- **test/server-entrypoint.sh**: Integrates output validation into
Docker tests
- **test/Dockerfile.server**: Copies validation script into container

## Configuration
- `VERBOSE=1` - Show command output in terminal
- `LOG_FILE=path` - Customize log location (default:
`openvpn-install.log`)
- `LOG_FILE=""` - Disable file logging
- `FORCE_COLOR=1` - Force colored output in non-TTY environments
2025-12-09 15:52:37 +01:00
Stanislas Lange adc4c6d220 Remove cloud provisioning solutions section from README
I don't maintain them, so I can't vouch that they work.

Close https://github.com/angristan/openvpn-install/pull/934 as well
2025-12-09 15:02:49 +01:00
Stanislas Lange 0ed153b8ec Update pull request template to clarify maintenance burden of added features 2025-12-09 14:17:19 +01:00
StanislasandGitHub a3389c126c Add Docker-based E2E testing (#1320)
### Summary
- Add automated end-to-end testing using Docker to verify the installation script works across 18 Linux distributions
- Add Oracle Linux 9 support to the installation script
- Drop support for EOL distributions (Debian 8/9/10, CentOS 7, Ubuntu 16.04) 
- Disable Digital Ocean droplets based end-to-end tests, let's use docker from now on

### Changes
**New test infrastructure:**
- `test/Dockerfile.server` - Multi-OS server image with `BASE_IMAGE` build arg
- `test/Dockerfile.client` - Ubuntu 24.04 client for connectivity testing
- `test/server-entrypoint.sh` - Runs install script, verifies files exist, asserts iptables NAT rules, starts OpenVPN
- `test/client-entrypoint.sh` - Connects to VPN, verifies tun0 interface, pings gateway
- `docker-compose.yml` - Orchestrates server + client with shared volume
- `.github/workflows/docker-test.yml` - CI matrix testing 18 OS variants
- `.github/workflows/test.yml` - Removed push/PR triggers, now manual only for DO tests
- `Makefile` - Local testing commands (`make test`, `make test-ubuntu-24.04`, etc.)

**Distributions tested (18 total):**
| Family | Versions |
|--------|----------|
| Ubuntu | 18.04, 20.04, 22.04, 24.04 |
| Debian | 11, 12 |
| Fedora | 40, 41 |
| Rocky Linux | 8, 9 |
| AlmaLinux | 8, 9 |
| Oracle Linux | 8, 9 |
| Amazon Linux | 2, 2023 |
| CentOS Stream | 9 |
| Arch Linux | latest |
2025-12-07 12:27:41 +01:00
Stanislas Lange 94c1af2b5d Remove Fedora 43 OS image from CI workflow 2025-12-04 23:18:15 +01:00
Stanislas Lange f92582fb2f Update Fedora OS images in CI workflow to include 42 and 43 2025-12-04 23:15:24 +01:00
Stanislas Lange 469bc2f883 Update OS images in CI workflow to include Debian 13 and remove 11 2025-12-04 23:12:57 +01:00
93284de7df Fix typo in FAQ
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas cc834519ff Fix path to easy-rsa tarball in checksum verification 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 39dd034717 Fix textlint terminology: websites -> sites 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas fafd10687f Disable MD041 rule for template files with HTML comments 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 7e9a713657 Fix shfmt formatting for constant comments 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 6b92f8a61f Quote shell variables in test.yml to fix shellcheck warnings 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 62c336022f Add permissions to test.yml for security best practices 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas cad43ad99e Add permissions to lint.yml for security best practices 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 3a0260e9b8 Make openvpn-install.sh executable 2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 77f28d1595 ci: add fetch-depth: 0 for super-linter v7 compatibility
Super-linter v7 requires full git history to find the default branch
for comparison. Without fetch-depth: 0, it fails with 'master branch
doesn't exist' error.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas b7557dd77f refactor: extract magic numbers to named constants
Move hardcoded values to readonly constants at the top of the script:
- CERT_VALIDITY_DAYS: certificate expiry (10 years)
- CRL_VALIDITY_DAYS: CRL expiry (10 years)
- EASYRSA_VERSION: easy-rsa version
- EASYRSA_SHA256: easy-rsa checksum

This improves maintainability and makes it easier to update these
values in the future.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 7304dbaac8 style: reduce shellcheck disables and fix warnings
- Remove unnecessary shellcheck disables (SC2164, SC1072, SC1073, SC1009)
- Add explanatory comments for remaining disables
- Fix SC2181: use direct exit code check instead of $?
- Fix SC2086: quote DH_KEY_SIZE variable
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas bfcd624592 docs: fix sysctl config path in FAQ (20 -> 99)
The script uses /etc/sysctl.d/99-openvpn.conf but the FAQ
incorrectly referenced /etc/sysctl.d/20-openvpn.conf
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 46a295b538 docs: update security section note for OpenVPN 2.5+
Replace the warning about outdated documentation with a note
clarifying that TLS 1.2 is kept as minimum for client compatibility
while acknowledging OpenVPN 2.5+ features.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas bf31e0ca64 docs: fix broken workflow link (push.yml -> lint.yml)
The workflow file was renamed but the README link was not updated.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 7c2c491fab ci: update appleboy/ssh-action from v0.1.6 to v1.2.0
Updates to a more recent stable version with bug fixes and
improvements.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 00f3cd1605 ci: update Super Linter from v4.1.0 to v7
The super-linter project has been moved to the super-linter org
and significantly updated. v7 includes many improvements and
bug fixes.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas d61b16f3b8 ci: replace deprecated set-output with GITHUB_OUTPUT
The set-output workflow command was deprecated in favor of
environment files. See:
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 960be1a658 security: add validation for root.hints download
Verify that the downloaded root.hints file is not empty and contains
expected DNS root server content before using it.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 94f0967878 security: add SHA256 checksum verification for easy-rsa download
Adds integrity verification to prevent supply chain attacks when
downloading easy-rsa from GitHub releases.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 1c5381cc03 fix: correct DNS prompt range from [1-12] to [1-13]
The prompt incorrectly showed [1-12] when option 13 (Custom DNS) is valid.
2025-12-04 23:04:11 +01:00
Stanislas LangeandStanislas 74dcf67844 fix: remove duplicate echo in resolvePublicIP error message 2025-12-04 23:04:11 +01:00
Stanislas Lange 7e32f6ae83 Fix mermaid diagram in README 2025-03-15 22:52:11 +01:00
Stanislas Lange 19e4b7961f CI: add Fedora 41 and remove 39 for e2e workflow 2025-03-10 10:27:19 +01:00
Stanislas Lange e2d4990ae1 Improve README 2025-01-06 17:25:26 +01:00
Stanislas Lange dc114f3243 Update distribution matrix for end-to-end tests 2024-11-07 20:49:42 +01:00
Stanislas Lange 0d58ddcb8c Update distribution matrix for end-to-end tests 2024-11-07 20:46:51 +01:00
Stanislas Lange 2ce1ee765e Remove centos-stream-8-x64 from test workflow
Not available on DO anymore
2024-07-12 18:22:34 +02:00
StanislasandGitHub a189535563 Set client and server certificates validity to 10 years (#1235)
Prevent #974
2024-07-12 18:16:19 +02:00
Stanislas Lange 67701fac77 CI: wait for dpkg lock in debian/ubuntu setup step 2024-05-16 20:37:23 +02:00
Stanislas Lange 0cc002e17d CI: wait for dpkg lock in debian/ubuntu setup step 2024-05-16 20:33:32 +02:00
Stanislas Lange a2725d61a3 CI: update actions/checkout to v4 2024-05-16 20:13:47 +02:00
Stanislas Lange 305e9868cf CI: update linux distributions used in end-to-end tests 2024-05-16 20:08:12 +02:00