# PKI (Public Key Infrastructure)

> Configure PKI on VyOS: create a CA, generate X.509 certificates, CRL, certificates for VPN and HTTPS, Let's Encrypt for Yandex Cloud and VK Cloud

Source: https://opennix.org/en/docs/vyos/pki/vyos-pki/


PKI (Public Key Infrastructure) in VyOS is a centralized system for managing certificates, keys, and Certificate Authorities (CA). VyOS provides built-in tools for generating, storing, and managing the cryptographic material used in VPN, HTTPS, and other secure services.

## Overview

PKI in VyOS is used for:

- **VPN authentication**: IPsec, OpenVPN with certificates instead of PSK
- **HTTPS services**: Secure web interface and REST API
- **Mutual authentication**: mTLS for critical services
- **Centralized management**: Your own CA for internal infrastructure
- **Certificate-based SSH**: SSH authentication with certificates

### PKI components

| Component | Description | Use |
|-----------|----------|---------------|
| **CA (Certificate Authority)** | Certificate authority | Signing certificates |
| **Certificate** | X.509 certificate | Identifying a device/service |
| **Private Key** | Private key | Encryption and signing |
| **Certificate Request (CSR)** | Certificate request | Obtaining a certificate from a CA |
| **CRL (Certificate Revocation List)** | List of revoked certificates | Validity checking |

### Typical workflow

1. **Create a CA** (root or intermediate)
2. **Generate a private key** for a service/device
3. **Create a CSR** (Certificate Signing Request)
4. **Sign the CSR** with your own CA or an external one
5. **Install the certificate** in VyOS
6. **Configure services** to use the certificate

## Basic configuration

### Creating your own CA

```bash
# Generate the private key for the CA
generate pki ca install ca-internal

# CA parameters (interactive):
# Country: RU
# State: Moscow
# Locality: Moscow
# Organization: My Company
# Common Name: My Company Root CA

# Check the created CA
show pki ca ca-internal

commit
save
```

### Generating a server certificate

```bash
# Generate the private key and certificate
generate pki certificate sign ca-internal install vyos-server

# Parameters:
# Common Name: vyos.example.com
# Subject Alternative Names (optional): DNS:vyos.example.com,IP:192.168.1.1

# Check
show pki certificate vyos-server

commit
save
```

### Importing an existing certificate

```bash
# Import a certificate from a file
generate pki certificate import vyos-cert certificate-file /tmp/certificate.pem

# Import a private key
generate pki key-pair import vyos-key private-key-file /tmp/private-key.pem

commit
save
```

### Using Let's Encrypt

```bash
# Import a Let's Encrypt certificate
generate pki certificate import letsencrypt-vyos \
  certificate-file /etc/letsencrypt/live/vyos.example.com/fullchain.pem \
  private-key-file /etc/letsencrypt/live/vyos.example.com/privkey.pem

# Configure HTTPS with Let's Encrypt
set service https certificates certificate letsencrypt-vyos

commit
save
```

## Advanced configuration

### Building a CA hierarchy (Root + Intermediate)

**Root CA**:

```bash
# Create the Root CA (offline, keep in a secure location)
generate pki ca install root-ca

# Parameters:
# Common Name: My Company Root CA
# Key size: 4096
# Validity: 3650 days (10 years)

commit
save
```

**Intermediate CA**:

```bash
# Create the Intermediate CA
generate pki ca sign root-ca install intermediate-ca

# Parameters:
# Common Name: My Company Intermediate CA
# Key size: 2048
# Validity: 1825 days (5 years)

commit
save
```

**Signing certificates with the Intermediate CA**:

```bash
# Certificates are signed by the intermediate CA
generate pki certificate sign intermediate-ca install server-cert

commit
save
```

### Generating a certificate with SAN (Subject Alternative Names)

```bash
# Certificate with multiple names
generate pki certificate sign ca-internal install multi-san-cert

# When prompted for SAN, specify:
# DNS:vyos.example.com,DNS:router.example.com,IP:192.168.1.1,IP:10.0.0.1

commit
save
```

### Wildcard certificate

```bash
# Wildcard certificate for a subdomain
generate pki certificate sign ca-internal install wildcard-cert

# Common Name: *.example.com
# Allows use for any subdomain: router.example.com, vpn.example.com, etc.

commit
save
```

### Client certificates for VPN

```bash
# Certificate for a VPN client
generate pki certificate sign ca-internal install client-alice

# Parameters:
# Common Name: alice@example.com
# Extended Key Usage: clientAuth

# Export to hand off to the client
show pki certificate client-alice pem

commit
save
```

### Certificate Revocation List (CRL)

```bash
# Create a CRL for the CA
generate pki crl ca-internal install crl-internal

# Revoke a certificate
set pki ca ca-internal crl revoke client-alice

# Update the CRL
generate pki crl ca-internal regenerate

commit
save
```

### Configuring validity periods

```bash
# Generate with a custom validity period (365 days)
generate pki certificate sign ca-internal install short-term-cert valid-days 365

commit
save
```

## Configuration examples

### Example 1: IPsec VPN with certificates

```bash
# Create a CA
generate pki ca install vpn-ca

# Certificate for the local router
generate pki certificate sign vpn-ca install vyos-site-a

# Certificate for the remote router (to be exported)
generate pki certificate sign vpn-ca install vyos-site-b

# IPsec configuration with certificates
set vpn ipsec authentication psk-secret 'fallback-psk'
set vpn ipsec esp-group ESP-VPN proposal 1 encryption aes256
set vpn ipsec esp-group ESP-VPN proposal 1 hash sha256

set vpn ipsec ike-group IKE-VPN key-exchange ikev2
set vpn ipsec ike-group IKE-VPN proposal 1 encryption aes256
set vpn ipsec ike-group IKE-VPN proposal 1 hash sha256

# Site-to-Site with certificates
set vpn ipsec site-to-site peer site-b authentication mode x509
set vpn ipsec site-to-site peer site-b authentication x509 ca-certificate vpn-ca
set vpn ipsec site-to-site peer site-b authentication x509 certificate vyos-site-a
set vpn ipsec site-to-site peer site-b ike-group IKE-VPN
set vpn ipsec site-to-site peer site-b local-address 203.0.113.1
set vpn ipsec site-to-site peer site-b remote-address 198.51.100.1
set vpn ipsec site-to-site peer site-b tunnel 0 esp-group ESP-VPN
set vpn ipsec site-to-site peer site-b tunnel 0 local prefix 192.168.1.0/24
set vpn ipsec site-to-site peer site-b tunnel 0 remote prefix 192.168.2.0/24

commit
save
```

### Example 2: OpenVPN with a CA and client certificates

```bash
# Create a CA for OpenVPN
generate pki ca install openvpn-ca

# Server certificate
generate pki certificate sign openvpn-ca install openvpn-server

# Client certificates
generate pki certificate sign openvpn-ca install client-user1
generate pki certificate sign openvpn-ca install client-user2

# DH parameters
generate pki dh install dh-2048 bits 2048

# OpenVPN server configuration
set interfaces openvpn vtun10 mode server
set interfaces openvpn vtun10 server subnet 10.8.0.0/24
set interfaces openvpn vtun10 tls ca-certificate openvpn-ca
set interfaces openvpn vtun10 tls certificate openvpn-server
set interfaces openvpn vtun10 tls dh-params dh-2048

commit
save

# Export the client certificate for the user
show pki ca openvpn-ca pem
show pki certificate client-user1 pem
show pki certificate client-user1 private key
```

### Example 3: HTTPS with your own CA

```bash
# Create a CA
generate pki ca install web-ca

# Certificate for the web interface with SAN
generate pki certificate sign web-ca install web-server

# When creating it, specify the SAN:
# DNS:vyos.example.com,IP:192.168.1.1

# Configure HTTPS
set service https certificates certificate web-server

# Restart HTTPS service
restart https

commit
save
```

### Example 4: Enterprise PKI with a hierarchy

```bash
# Root CA (created once, stored offline)
generate pki ca install company-root-ca
# CN: Company Name Root CA
# Validity: 7300 days (20 years)

# Intermediate CA for servers
generate pki ca sign company-root-ca install servers-ca
# CN: Company Name Servers CA
# Validity: 3650 days (10 years)

# Intermediate CA for clients
generate pki ca sign company-root-ca install clients-ca
# CN: Company Name Clients CA
# Validity: 3650 days (10 years)

# Server certificates are signed by servers-ca
generate pki certificate sign servers-ca install web-server
generate pki certificate sign servers-ca install vpn-server

# Client certificates are signed by clients-ca
generate pki certificate sign clients-ca install client-alice
generate pki certificate sign clients-ca install client-bob

commit
save
```

### Example 5: Let's Encrypt with auto-renewal

```bash
# Install certbot (on VyOS)
sudo apt-get update
sudo apt-get install certbot

# Obtain the certificate (HTTP-01 challenge)
sudo certbot certonly --standalone \
  --preferred-challenges http \
  --email admin@example.com \
  --agree-tos \
  -d vyos.example.com

# Import into VyOS
generate pki certificate import letsencrypt-vyos \
  certificate-file /etc/letsencrypt/live/vyos.example.com/fullchain.pem \
  private-key-file /etc/letsencrypt/live/vyos.example.com/privkey.pem

# Configure HTTPS
set service https certificates certificate letsencrypt-vyos

commit
save
```

Auto-renewal script `/config/scripts/renew-letsencrypt.sh`:

```bash
#!/bin/bash

# Renew the certificate
sudo certbot renew --quiet

# Check the renewal
if [ $? -eq 0 ]; then
    # Re-import into VyOS
    /usr/libexec/vyos/op_mode/pki.py import certificate \
      letsencrypt-vyos \
      /etc/letsencrypt/live/vyos.example.com/fullchain.pem \
      /etc/letsencrypt/live/vyos.example.com/privkey.pem

    # Restart HTTPS
    sudo systemctl restart vyos-http-api-server

    logger -t letsencrypt "Certificate renewed successfully"
else
    logger -t letsencrypt -p user.err "Certificate renewal failed"
fi
```

Task Scheduler for auto-renewal:

```bash
set system task-scheduler task renew-letsencrypt interval '0 3 * * *'
set system task-scheduler task renew-letsencrypt executable path '/config/scripts/renew-letsencrypt.sh'
```

### Example 6: Wildcard certificate for multiple services

```bash
# Create a CA
generate pki ca install internal-ca

# Wildcard certificate
generate pki certificate sign internal-ca install wildcard-example-com
# CN: *.example.com

# Use it for various services
# HTTPS
set service https certificates certificate wildcard-example-com

# OpenVPN
set interfaces openvpn vtun0 tls certificate wildcard-example-com

commit
save
```

## Monitoring and diagnostics

### Viewing certificates and CAs

```bash
# Show all CAs
show pki ca

# Details of a specific CA
show pki ca ca-internal

# Export a CA to PEM
show pki ca ca-internal pem

# Show all certificates
show pki certificate

# Details of a specific certificate
show pki certificate vyos-server

# Export a certificate
show pki certificate vyos-server pem

# Export a private key
show pki certificate vyos-server private key
```

### Checking the validity period

```bash
# Check the certificate
show pki certificate vyos-server

# The output includes:
# - Issuer (who issued it)
# - Subject (who it was issued to)
# - Valid From / Valid To (validity period)
# - Subject Alternative Names
```

### Verifying the certificate chain

```bash
# Verify that the certificate was signed by the correct CA
show pki certificate vyos-server

# Verify with openssl (in the shell)
openssl verify -CAfile ca.pem certificate.pem
```

### Testing HTTPS with a certificate

```bash
# From the client
curl -k https://192.168.1.1/
curl --cacert ca.crt https://vyos.example.com/

# Check certificate details
openssl s_client -connect vyos.example.com:443 -showcerts
```

### Checking IPsec with certificates

```bash
# Check the configuration
show vpn ipsec sa

# IPsec logs
show log vpn ipsec

# Certificate details in IPsec
sudo swanctl --list-certs
```

### Monitoring certificate expiration

Script `/config/scripts/check-cert-expiry.sh`:

```bash
#!/bin/bash

ALERT_DAYS=30
CERTS="vyos-server openvpn-server"

for cert in $CERTS; do
    # Get the expiration date
    EXPIRY=$(cli-shell-api showConfig pki certificate $cert | grep "Valid To" | awk '{print $3}')

    # Convert and check (simplified)
    # In production, use full-featured date parsing

    # If close to expiration, send an alert
    # echo "Certificate $cert expires on $EXPIRY" | mail -s "Cert Expiry Alert" admin@example.com

    logger -t cert-monitor "Checked certificate $cert"
done
```

Task Scheduler:

```bash
set system task-scheduler task cert-monitor interval '0 0 * * *'
set system task-scheduler task cert-monitor executable path '/config/scripts/check-cert-expiry.sh'
```

## Troubleshooting

### Problem: The certificate does not validate

**Diagnostics**:

```bash
# Check the certificate
show pki certificate vyos-server

# Check the CA
show pki ca ca-internal

# Check with openssl
openssl x509 -in certificate.pem -text -noout
openssl verify -CAfile ca.pem certificate.pem
```

**Solution**:

```bash
# Make sure the certificate was signed by the correct CA
# Check the chain: Certificate -> Intermediate CA -> Root CA

# Re-sign if necessary
generate pki certificate sign ca-internal install vyos-server

commit
save
```

### Problem: IPsec does not work with certificates

**Diagnostics**:

```bash
# Check the configuration
show configuration vpn ipsec

# Logs
show log vpn ipsec | match certificate

# Details
sudo swanctl --list-certs
sudo ipsec statusall
```

**Solution**:

```bash
# Make sure the CA and certificate are configured
show pki ca vpn-ca
show pki certificate vyos-site-a

# Check the IPsec configuration
set vpn ipsec site-to-site peer site-b authentication mode x509
set vpn ipsec site-to-site peer site-b authentication x509 ca-certificate vpn-ca
set vpn ipsec site-to-site peer site-b authentication x509 certificate vyos-site-a

commit
save

# Restart IPsec
restart ipsec
```

### Problem: HTTPS does not use the new certificate

**Solution**:

```bash
# Check the configuration
show configuration service https certificates

# Set the certificate
set service https certificates certificate new-cert

commit
save

# Restart HTTPS
restart https
```

### Problem: The certificate has expired

**Solution**:

```bash
# Generate a new certificate
generate pki certificate sign ca-internal install vyos-server-new

# Update the service configuration
set service https certificates certificate vyos-server-new

# Delete the old one
delete pki certificate vyos-server

commit
save
```

### Problem: The private key is corrupted

**Solution**:

```bash
# Create a new key-certificate pair
generate pki certificate sign ca-internal install new-cert

# Update all references to the old certificate

commit
save
```

### Problem: The CA is not trusted by clients

**Solution**:

Export the CA and install it on the client systems:

```bash
# On VyOS
show pki ca ca-internal pem > company-ca.crt

# On a Linux client
sudo cp company-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

# On Windows
# Import via certmgr.msc into "Trusted Root Certification Authorities"

# On macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain company-ca.crt
```

## Best practices

### 1. CA hierarchy

Use a Root + Intermediate CA:

```bash
# Root CA - offline, long validity period
# Intermediate CA - online, signs certificates
```

### 2. Validity periods

Reasonable periods:

```bash
# Root CA: 10-20 years
# Intermediate CA: 5-10 years
# Server certificates: 1-3 years
# Client certificates: 1-2 years
```

### 3. Key sizes

```bash
# CA: 4096 bits
# Server certificates: 2048 bits (balance of security/performance)
# Client certificates: 2048 bits
```

### 4. Subject Alternative Names

Always use SAN for compatibility:

```bash
# CN: vyos.example.com
# SAN: DNS:vyos.example.com,DNS:router.example.com,IP:192.168.1.1
```

### 5. Protecting private keys

```bash
# Restrict access to the configuration
sudo chmod 600 /config/config.boot

# Keep the Root CA offline
# Use a passphrase for critical keys (outside VyOS)
```

### 6. Certificate Revocation

Configure a CRL for revocation:

```bash
set pki ca ca-internal crl revoke compromised-cert
generate pki crl ca-internal regenerate
```

### 7. Expiration monitoring

Set up automatic checks:

```bash
set system task-scheduler task cert-monitor interval '0 0 * * *'
```

### 8. Documentation

Document all certificates:

```bash
# /config/pki-inventory.txt
# vyos-server: CN=vyos.example.com, Expires: 2026-10-14, Used by: HTTPS
# openvpn-server: CN=vpn.example.com, Expires: 2026-10-14, Used by: OpenVPN
```

### 9. Backups

Back up the PKI:

```bash
# Backup of all certificates and keys
show pki ca > /config/backup/pki-ca-backup.txt
show pki certificate > /config/backup/pki-cert-backup.txt

# Regular configuration backups
/opt/vyatta/sbin/vyatta-save-config.pl /config/backup/config.boot.$(date +%Y%m%d)
```

### 10. Testing before production

Test certificates before deployment:

```bash
# Validity check
openssl verify -CAfile ca.pem certificate.pem

# Validity period check
openssl x509 -in certificate.pem -noout -dates

# SAN check
openssl x509 -in certificate.pem -noout -text | grep "Subject Alternative Name" -A1
```

## Useful commands

```bash
# Show all CAs
show pki ca

# Show all certificates
show pki certificate

# CA details
show pki ca ca-internal

# Certificate details
show pki certificate vyos-server

# Export a CA to PEM
show pki ca ca-internal pem

# Export a certificate
show pki certificate vyos-server pem

# Export a private key
show pki certificate vyos-server private key

# Generate a CA
generate pki ca install new-ca

# Generate a certificate
generate pki certificate sign ca-internal install new-cert

# Import a certificate
generate pki certificate import cert-name certificate-file /path/to/cert.pem

# Import a key
generate pki key-pair import key-name private-key-file /path/to/key.pem

# Configuration
show configuration pki

# OpenSSL commands for verification
openssl x509 -in cert.pem -text -noout
openssl verify -CAfile ca.pem cert.pem
openssl s_client -connect host:443 -showcerts
```

## Integration with other features

### PKI + IPsec VPN

```bash
set vpn ipsec site-to-site peer site-b authentication mode x509
set vpn ipsec site-to-site peer site-b authentication x509 ca-certificate vpn-ca
set vpn ipsec site-to-site peer site-b authentication x509 certificate site-a-cert
```

### PKI + OpenVPN

```bash
set interfaces openvpn vtun0 tls ca-certificate openvpn-ca
set interfaces openvpn vtun0 tls certificate server-cert
set interfaces openvpn vtun0 tls dh-params dh-2048
```

### PKI + HTTPS

```bash
set service https certificates certificate web-cert
```

### PKI + SSH (certificates)

```bash
# Using an SSH CA for authentication (advanced setup)
# Requires additional OpenSSH configuration
```

## Conclusion

PKI (Public Key Infrastructure) in VyOS provides centralized certificate management for all secure services. The built-in tools let you create your own CAs, generate certificates, manage their lifecycle, and integrate with external PKI systems.

Key benefits of PKI in VyOS:
- Centralized certificate management
- Your own CA for internal infrastructure
- Support for a CA hierarchy (Root + Intermediate)
- Integration with VPN (IPsec, OpenVPN)
- Let's Encrypt support
- Certificate Revocation Lists (CRL)

Recommendations for production:
- Use a CA hierarchy (Root offline + Intermediate online)
- Apply reasonable validity periods
- Use SAN for all certificates
- Protect private keys
- Set up expiration monitoring
- Document all certificates
- Create backups regularly
- Test before production
- Use a CRL to revoke compromised certificates

PKI in VyOS delivers enterprise-grade certificate management for building secure infrastructure with certificate-based authentication, eliminating the need for PSK (Pre-Shared Keys) and providing centralized control over cryptographic material.

