Package setup for building files at any host computer#

sudo apt install easy-rsa openssl openvpn

Package setup for OpenVPN server#

sudo apt install openvpn

Create directory for building and keeping keyfiles#

mkdir ~/vpn_repo
cd ~/vpn_repo

*** From here on, everything happens at ~/vpn_repo !!! ***#

Fetch & prepare easy-tls#

wget https://raw.githubusercontent.com/TinCanTech/easy-tls/refs/heads/master/easytls
chmod 750 easytls

For creating all the needed OpenVPN server files#

cat >server.sh

#!/bin/bash

# cert & ca expiry 10 years
export EASYRSA_KEY_SIZE=2048
export EASYRSA_CA_EXPIRE=3650
export EASYRSA_CERT_EXPIRE=3650

TARGET=$1
USER=$2
PASS=$3

if [ -z $TARGET ]
then
  echo "Give servername as arg"
  exit
fi

make-cadir $TARGET
if [ $? -eq 0 ]
  then
  cd $TARGET

  # build server cert package
  ./easyrsa init-pki
  echo $TARGET | ./easyrsa build-ca nopass
  ./easyrsa gen-dh
  echo yes | ./easyrsa build-server-full $TARGET nopass

  # prepare tls-auth key
  if [[ ! -d pki/easytls ]]
  then
    ../easytls init-tls
    ../easytls build-tls-auth
  fi

  cd ..
  mkdir -p out
  # symlink all files needed on server side
  ln -srf $TARGET/pki/private/$TARGET.key out/
  ln -srf $TARGET/pki/ca.crt out/${TARGET}_ca.crt
  ln -srf $TARGET/pki/easytls/tls-auth.key out/${TARGET}_tls-auth.key
  ln -srf $TARGET/pki/dh.pem out/${TARGET}_dh.pem
  ln -srf $TARGET/pki/issued/$TARGET.crt out/

  echo "#### OpenVPN server files"
  find out | tail +2
  echo "####"
  echo "Copy these files to server /etc/openvpn/server/"
fi

For creating client profiles#

cat >gen_user.sh

#!/bin/bash

# 10 year expiry
export EASYRSA_KEY_SIZE=2048
export EASYRSA_CA_EXPIRE=3650
export EASYRSA_CERT_EXPIRE=3650

TARGET=$1
USER=$2
PASS=$3

if [[ ! -d $TARGET || -z $USER ]]
then
  echo "Give target server name and username as args"
  exit
fi

cd $TARGET

if [ -z $PASS ]
then
  echo yes | ./easyrsa build-client-full $USER nopass
else
  echo yes | EASYRSA_PASSOUT=pass:$PASS ./easyrsa build-client-full $USER
fi

# create inline tls-auth
../easytls inline-tls-auth $USER

# create user client profile
cat ../client_template.ovpn >../${TARGET}_${USER}.ovpn
cat pki/easytls/$USER.inline >>../${TARGET}_${USER}.ovpn

# list generated files
cd ..
echo "#### inline client profile"
ls ${TARGET}_$USER*ovpn
echo ""

For revoking client profile if needed#

cat >revoke_user.sh

#!/bin/bash

TARGET=$1
USER=$2

if [[ ! -d $TARGET || -z $USER ]]
then
  echo "Give server and username as args"
  exit
fi

if [ ! -f $TARGET/pki/issued/$USER.crt ]
then
  exit
fi

cd $TARGET

echo yes | ./easyrsa revoke $USER
./easyrsa gen-crl

echo "#### copy and activate the crl file at server"
echo ""

Client profile template#

remote server.hostname.here

proto udp
port 12345
dev tun
cipher AES-256-CBC

topology subnet
pull

tls-client
auth-nocache
remote-cert-tls server

OpenVPN config for server host#

cat >sample.conf

## networking
port 12345
dev tun_s1
proto udp
server 172.16.10.0 255.255.255.0
topology subnet
client-to-client
keepalive 10 120

## misc
verb 3
client-config-dir /etc/openvpn/ccd
persist-key
persist-tun

## tunnel/ciphersuite
tls-server
auth sha1
key-direction 0
cipher AES-256-CBC

## keyfiles
ca /etc/openvpn/server/sample_ca.crt
key /etc/openvpn/server/sample.key
cert /etc/openvpn/server/sample.crt
dh /etc/openvpn/server/sample_dh.pem
tls-auth /etc/openvpn/server/sample_tls-auth.key

Prepare helper scripts#

chmod 750 *.sh

Example 1: Create server files#

./gen_server.sh sample
# copy ^ generated files to target server at /etc/openvpn/server/

# copy server config to target server
# scp sample.conf root@server:/etc/openvpn/server/

Example 2: Prepare and start OpenVPN server#

NOTE: this happens at server host

sudo systemctl enable openvpn-server@sample
sudo systemctl start openvpn-server@sample

Example 3: Create client profiles and test client#

# generate user/client profiles for sample server
./gen_user.sh sample user1
./gen_user.sh sample user2
ls *ovpn

# test client
sudo openvpn sample_user1.ovpn

# succesful connection output
# 2025-04-03 21:59:56 [sample] Peer Connection Initiated with [AF_INET]server:12345
# 2025-04-03 21:59:56 TUN/TAP device tun1 opened
# 2025-04-03 21:59:56 net_addr_v4_add: 172.16.10.10/24 dev tun1
# 2025-04-03 21:59:56 Initialization Sequence Completed

# private server address will always be 172.16.10.1

# clients will get random 172.16.10.x address
# see below for static config

OpenVPN CCD rule example at server config side#

# create CCD file AT SERVER by vpn username
sudo cat >/etc/openvpn/ccd/user1
ifconfig-push 172.16.10.8 255.255.255.0
# user1 client host ^ will get this private ip address

# make similar files for any other clients