Here's how you could install and configure
OpenVPN in the Azure cloud.
In this instance the pre-built vm was selected
Part of the default install will be Azure providing you with a PEM
key.
You'll want to save this and possible store it safely somewhere.
1.
Download PuTTY application
2.
With Azure, it provides you a PEM key to access
the box using SSH. (this is the password so to speak). With PUTTY
being a super popular way to SSH to a box, the PEM key needs to be converted to
a PPK (Private Key File)
3.
Launch the PuTTYgen app.
Click Conversions > Import Key.
4.
Select
the key file you used to generate your server.
With Azure, you dont need a keyphrase, you can just click "Save
Private Key"
5.
Save private key.
- Close PuTTYgen.
- Connect with SSH by using
PuTTY
- Open PuTTY, and configure
your connection values and SSH key.
- In the Host Name
(or IP address) box, enter the username and public IP address of
the machine (for example, username@192.XXX.XXX.XX).
The default user for azure ssh is "azureuser" - Validate that the Port is 22 and
the Connection type is SSH.
- In the Category tree,
expand SSH and Auth, select
"Credentials"
- Next to the Private
key file for authentication box, select Browse, and
then search for the private key file (<filename>.ppk) of your
public and private key pair.
- In the Category tree,
select Session.
- Under Saved
Sessions, enter a name for the session, and then select Save.
- In the Saved
Sessions list, select the name of your session, and then
select Load.
- Select Open.
The SSH session opens.
- The default user for azure
ssh is "azureuser"
- Logon to the server, you
will be prompted to enter the user name, and if you have the key
configured properly, you will be logged in.
- You will be asked to agree
to the license
- You will then be asked a
series of configuration question
21. In
this example, all the defaults were selected.
22. You
will also be presented with the random generated GUI password, so look for that
- Once the questions are
answered, the final bits of configuration will be completed, and you will
be presented with the logon information for the GUI
- Update the Ubunut
installation with the latest
- sudo apt update
26. sudo
apt upgrade -y
- In Azure, go to Network
Settings
28. Its
a good idea to update the default SSH rule to be the WAN IP of your network to
reduce chances of an attack through the SSH PORT
29. Click
on the "SSH" and then change the SOURCE from ANY to IP Addresses
30. Then
in the source IP put in your WAN ip
- SAVE the changes and
select +Create Port Rule
- Set the destination port
ranges to be "943" (default port used by OpenVPN Admin)
- Give it a NAME and then
press add
- It will look like this
when done
- If you are going to be
adding some certificates to this box,
you may need to add port '80' for the system to download the challenge files from the server - Additionally, you will
need to open port 443 and 1194 so that users can access this
box
- Now try and access the
server with the IP and /admin
provided in the example
Select Advanced
38. Select
CONTINUE
- The "UNSECURE"
means you have no CERTS for the box, yet.
- Enter in the credentials
provided when you were configuring the system in the cli
- Enter in your credentials
42. openvpn
/ CvIrJINl4CBp
- You'll get prompted with a
License Agreement
- You'll be in the GUI now
- Change the GUI openvpn
admin password
46. Goto
USERS -> OpenVPN -> Reset Password
- now lest add this new
server to our existing license (you can share the licences among different
servers)
- Logon to your OpenVPN.com
license site.
49. Copy
the Activation key from your subscription
- Select
"ACTIVATION" and then paste the key into the box and press
"ACTIVATE"
- If successful you will be
taken to a screen similar
- The above picture shows
"30" in yellow as the number of available licenses this account
has, and the green shows the number of licenses in use on other servers.
- Now click on Certificate
management
- Go into the DNS provider
and add in the DNS name for this box and its ip.
in my case, the domain is hosted in GoDaddy, so I go in an add an A record name for the box and its IP address
- This link is openVPN server's link how to install Lets encrypt. It works very well
- Access Server: Install Let's Encrypt SSL Certificates and Automate it via CertBot – OpenVPN Support Center
I used Option "B" (Use the HTTP-01 challenge)
This is a copy/paste from the above link, i'm using htis for my own references, i suggest you follow the above link. Confirm that the hostname resolves to your Access Server public IP address.
Confirm that TCP 80 is allowed through your cloud firewall, security group, router, or host firewall.
Issue the certificate:
Replace VPN-NAME.COMPANY.COM and admin@example.com with your own values for your system
certbot certonly --standalone --preferred-challenges http \ -d VPN-NAME.COMPANY.COM \ --deploy-hook /usr/local/sbin/openvpnas-deploy.sh \ --agree-tos -m admin@example.com --no-eff-emailTo register without an email address, replace the email options with:
--register-unsafely-without-email
- ff
Verify the certificate from a browser, the Admin Web UI, and optionally from the command line.
Verify from a browser
Open the Admin Web UI using the hostname:
https://vpn.example.com/adminOpen the Client Web UI:
https://vpn.example.comConfirm that the browser no longer displays a self-signed certificate warning.
View the certificate details and confirm:
The hostname matches.
The issuer is Let's Encrypt.
The certificate is currently valid.
The browser trusts the certificate chain.
Note
Browser interfaces vary. Some browsers display a lock, tune, or site information icon rather than a green padlock.
Verify from the Admin Web UI
Sign in to the Admin Web UI.
Select Certificate Management,
Confirm that the Web Server Certificate tab displays the Let's Encrypt certificate.
Select See full certificate details, if needed.
Verify the subject, issuer, and expiration date.
Verify from the command line
Connect to the console and get root privileges.
Run:
sacli ConfigQuery|grep cs.cert|cut -d '"' -f 4|sed 's/\\n/\n/g'|openssl x509 -text -noout|head -n 11Example output:
Certificate: Data: Version: 3 (0x2) Serial Number: 05:d8:37:0a:10:42:f9:13:96:83:4d:07:de:78:36:aa:07:df Signature Algorithm: ecdsa-with-SHA384 Issuer: C = US, O = Let's Encrypt, CN = YE2 Validity Not Before: Jul 15 16:58:37 2026 GMT Not After : Oct 13 16:58:36 2026 GMT Subject: CN = vpn.example.comExpected result: The Admin Web UI and Client Web UI present a browser-trusted certificate issued by Let's Encrypt for your hostname
Certbot stores the original issuance settings, including the selected challenge plugin and deploy hook, in the certificate’s renewal configuration. When the certificate becomes eligible for renewal, Certbot reuses those settings and runs the deploy hook after a successful renewal.
Package-based Certbot installations may include an automated renewal scheduler. Depending on your operating system and installation method, renewal may be scheduled through a systemd timer or cron job. Review the Certbot instructions for your installation method to confirm how automated renewal is configured.
Certbot checks the certificate regularly and renews when it becomes eligible. After a successful renewal, the deploy hook imports the renewed certificate into Access Server.
Note
For a 90-day Let's Encrypt certificate, Certbot typically renews the certificate when approximately 30 days of validity remain. This usually means renewal occurs around 60 days after issuance. The deploy hook runs after the successful renewal. Use certbot certificates to review the certificate's current expiration date.
Confirm the timer is active and scheduled:
Ubuntu and Debian:
systemctl status certbot.timerExample output:
● certbot.timer - Run certbot twice daily Loaded: loaded (/usr/lib/systemd/system/certbot.timer; enabled; preset: enabled) Active: active (waiting) since Wed 2026-07-15 17:43:21 UTC; 1h 12min ago Trigger: Thu 2026-07-16 00:26:25 UTC; 5h 30min left Triggers: ● certbot.serviceThe Trigger field shows the exact time it will check and verify.
Note
If neither timer is available, your Certbot installation may use a cron job or may require you to configure automated renewal. Review the Certbot instructions for your operating system and installation method, then confirm that the scheduled task runs
certbot renew.
Verify how often the timer runs:
Ubuntu and Debian:
systemctl cat certbot.timerRed Hat Enterprise Linux:
systemctl cat certbot-renew.timerExample output:
# /usr/lib/systemd/system/certbot.timer [Unit] Description=Run certbot twice daily [Timer] OnCalendar=*-*-* 00,12:00:00 RandomizedDelaySec=43200 Persistent=true [Install] WantedBy=timers.targetThe scheduler may include a randomized delay so that large numbers of Certbot clients don't contact the certificate authority at exactly the same time.
Important
A timer running once or twice a day doesn’t mean that Certbot renews the certificate every time. Each run checks the managed certificates and exits without changing them when no certificate is eligible for renewal. Frequent checks are normal and harmless.
Review the next and previous timer runs:
Ubuntu and Debian:
systemctl list-timers --all certbot.timerExample output:
NEXT LEFT LAST PASSED UNIT ACTIVATES Thu 2026-07-16 00:26:25 UTC 5h 26min - - certbot.timer certbot.service 1 timers listed.The output shows when the timer last ran (LAST / PASSED) and when it will run again (NEXT / LEFT).
Verify that Certbot is tracking your certificates:
certbot certificatesExample output:
Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Found the following certs: Certificate Name: vpn.example.com Serial Number: 5d8370a1042f91396834d07de7836aa07df Key Type: ECDSA Domains: vpn.example.com Expiry Date: 2026-10-13 16:58:36+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/vpn.example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/vpn.example.com/privkey.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Confirm that:
Certificate Name matches the
DOMAINvalue in the deploy hooks.Domains contains the expected hostname or wildcard names.
Expiry Date shows the certificate as valid.
The certificate and private key paths use the expected lineage directory.
Run a dry-run renewal against Let's Encrypt's staging environment to test the automatic renewal and the deploy hook:
certbot renew --dry-run --run-deploy-hooksExample output:
Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Processing /etc/letsencrypt/renewal/vpn.example.com.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Account registered. Simulating renewal of an existing certificate for vpn.example.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/vpn.example.com/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The
--run-deploy-hooksoption tests the saved deploy hook after a successful dry run. Certbot uses the current active certificate when running the deploy hook; it doesn't install the temporary staging certificate.
55.