## 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
* Update FAQ with IPv6 prefix policies for ULA addresses
Most operating systems will prefer IPv4 rather than IPv6 ULA, which defeats the purpose of redirect-gateway ipv6. It's nothing the script can do to automate this.