How To Set Up an OpenVPN Server on Debian 10

A previous version of this tutorial was written by Justin Ellingwood


Want to access the Internet safely and securely from your smartphone or laptop when connected to an untrusted network such as the WiFi of a hotel or coffee shop? A Virtual Private Network (VPN) allows you to traverse untrusted networks privately and securely as if you were on a private network. The traffic emerges from the VPN server and continues its journey to the destination.

When combined with HTTPS connections, this setup allows you to secure your wireless logins and transactions. You can circumvent geographical restrictions and censorship, and shield your location and any unencrypted HTTP traffic from the untrusted network.

OpenVPN is a full-featured, open-source Secure Socket Layer (SSL) VPN solution that accommodates a wide range of configurations. In this tutorial, you will set up an OpenVPN server on a Debian 10 server and then configure access to it from Windows, macOS, iOS and/or Android. This tutorial will keep the installation and configuration steps as simple as possible for each of these setups.

Note: If you plan to set up an OpenVPN server on a DigitalOcean Droplet, be aware that we, like many hosting providers, charge for bandwidth overages. For this reason, please be mindful of how much traffic your server is handling.

See this page for more info.


To complete this tutorial, you will need access to a Debian 10 server to host your OpenVPN service. You will need to configure a non-root user with sudo privileges before you start this guide. You can follow our Debian 10 initial server setup guide to set up a user with appropriate permissions. The linked tutorial will also set up a firewall, which is assumed to be in place throughout this guide.

Additionally, you will need a separate machine to serve as your certificate authority (CA). While it’s technically possible to use your OpenVPN server or your local machine as your CA, this is not recommended as it opens up your VPN to some security vulnerabilities. Per the official OpenVPN documentation, you should place your CA on a standalone machine that’s dedicated to importing and signing certificate requests. For this reason, this guide assumes that your CA is on a separate Debian 10 server that also has a non-root user with sudo privileges and a basic firewall.

Please note that if you disable password authentication while configuring these servers, you may run into difficulties when transferring files between them later on in this guide. To resolve this issue, you could re-enable password authentication on each server. Alternatively, you could generate an SSH keypair for each server, then add the OpenVPN server’s public SSH key to the CA machine’s authorized_keys file and vice versa. See How to Set Up SSH Keys on Debian 10 for instructions on how to perform either of these solutions.

When you have these prerequisites in place, you can move on to Step 1 of this tutorial.

Step 1 — Installing OpenVPN and EasyRSA

To start off, update your VPN server’s package index and install OpenVPN. OpenVPN is available in Debian’s default repositories, so you can use apt for the installation:

  • sudo apt update
  • sudo apt install openvpn

OpenVPN is a TLS/SSL VPN. This means that it utilizes certificates in order to encrypt traffic between the server and clients. To issue trusted certificates, you will set up your own simple certificate authority (CA). To do this, we will download the latest version of EasyRSA, which we will use to build our CA public key infrastructure (PKI), from the project’s official GitHub repository.

As mentioned in the prerequisites, we will build the CA on a standalone server. The reason for this approach is that, if an attacker were able to infiltrate your server, they would be able to access your CA private key and use it to sign new certificates, giving them access to your VPN. Accordingly, managing the CA from a standalone machine helps to prevent unauthorized users from accessing your VPN. Note, as well, that it’s recommended that you keep the CA server turned off when not being used to sign keys as a further precautionary measure.

To begin building the CA and PKI infrastructure, use wget to download the latest version of EasyRSA on both your CA machine and your OpenVPN server. To get the latest version, go to the Releases page on the official EasyRSA GitHub project, copy the download link for the file ending in .tgz, and then paste it into the following command:

  • wget -P ~/

Then extract the tarball:

  • cd ~
  • tar xvf EasyRSA-unix-v3.0.6.tgz

You have successfully installed all the required software on your server and CA machine. Continue on to configure the variables used by EasyRSA and to set up a CA directory, from which you will generate the keys and certificates needed for your server and clients to access the VPN.

Step 2 — Configuring the EasyRSA Variables and Building the CA

EasyRSA comes installed with a configuration file which you can edit to define a number of variables for your CA.

On your CA machine, navigate to the EasyRSA directory:

  • cd ~/EasyRSA-v3.0.6/

Inside this directory is a file named vars.example. Make a copy of this file, and name the copy vars without a file extension:

  • cp vars.example vars

Open this new file using your preferred text editor:

  • nano vars

Find the settings that set field defaults for new certificates. It will look something like this:

. . .  #set_var EASYRSA_REQ_COUNTRY    "US" #set_var EASYRSA_REQ_PROVINCE   "California" #set_var EASYRSA_REQ_CITY       "San Francisco" #set_var EASYRSA_REQ_ORG        "Copyleft Certificate Co" #set_var EASYRSA_REQ_EMAIL      "" #set_var EASYRSA_REQ_OU         "My Organizational Unit"  . . . 

Uncomment these lines and update the highlighted values to whatever you’d prefer, but do not leave them blank:

. . .  set_var EASYRSA_REQ_COUNTRY    "US" set_var EASYRSA_REQ_PROVINCE   "NewYork" set_var EASYRSA_REQ_CITY       "New York City" set_var EASYRSA_REQ_ORG        "DigitalOcean" set_var EASYRSA_REQ_EMAIL      "" set_var EASYRSA_REQ_OU         "Community"  . . . 

When you are finished, save and close the file.

Within the EasyRSA directory is a script called easyrsa which is called to perform a variety of tasks involved with building and managing the CA. Run this script with the init-pki option to initiate the public key infrastructure on the CA server:

  • ./easyrsa init-pki
. . . init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /home/sammy/EasyRSA-v3.0.6/pki

After this, call the easyrsa script again, following it with the build-ca option. This will build the CA and create two important files — ca.crt and ca.key — which make up the public and private sides of an SSL certificate.

  • ca.crt is the CA’s public certificate file which, in the context of OpenVPN, the server and the client use to inform one another that they are part of the same web of trust and not someone performing a man-in-the-middle attack. For this reason, your server and all of your clients will need a copy of the ca.crt file.
  • ca.key is the private key which the CA machine uses to sign keys and certificates for servers and clients. If an attacker gains access to your CA and, in turn, your ca.key file, they will be able to sign certificate requests and gain access to your VPN, impeding its security. This is why your ca.key file should only be on your CA machine and that, ideally, your CA machine should be kept offline when not signing certificate requests as an extra security measure.

If you don’t want to be prompted for a password every time you interact with your CA, you can run the build-ca command with the nopass option, like this:

  • ./easyrsa build-ca nopass

In the output, you’ll be asked to confirm the common name for your CA:

. . . Common Name (eg: your user, host, or server name) [Easy-RSA CA]:

The common name is the name used to refer to this machine in the context of the certificate authority. You can enter any string of characters for the CA’s common name but, for simplicity’s sake, press ENTER to accept the default name.

With that, your CA is in place and it’s ready to start signing certificate requests.

Step 3 — Creating the Server Certificate, Key, and Encryption Files

Now that you have a CA ready to go, you can generate a private key and certificate request from your server and then transfer the request over to your CA to be signed, creating the required certificate. You’re also free to create some additional files used during the encryption process.

Start by navigating to the EasyRSA directory on your OpenVPN server:

  • cd EasyRSA-v3.0.6/

From there, run the easyrsa script with the init-pki option. Although you already ran this command on the CA machine, it’s necessary to run it here because your server and CA will have separate PKI directories:

  • ./easyrsa init-pki

Then call the easyrsa script again, this time with the gen-req option followed by a common name for the machine. Again, this could be anything you like but it can be helpful to make it something descriptive. Throughout this tutorial, the OpenVPN server’s common name will simply be “server”. Be sure to include the nopass option as well. Failing to do so will password-protect the request file which could lead to permissions issues later on:

Note: If you choose a name other than “server” here, you will have to adjust some of the instructions below. For instance, when copying the generated files to the /etc/openvpn directory, you will have to substitute the correct names. You will also have to modify the /etc/openvpn/server.conf file later to point to the correct .crt and .key files.

  • ./easyrsa gen-req server nopass

This will create a private key for the server and a certificate request file called server.req. Copy the server key to the /etc/openvpn/ directory:

  • sudo cp ~/EasyRSA-v3.0.6/pki/private/server.key /etc/openvpn/

Using a secure method (like SCP, in our example below), transfer the server.req file to your CA machine:

  • scp ~/EasyRSA-v3.0.6/pki/reqs/server.req sammy@your_CA_ip:/tmp

Next, on your CA machine, navigate to the EasyRSA directory:

  • cd EasyRSA-v3.0.6/

Using the easyrsa script again, import the server.req file, following the file path with its common name:

  • ./easyrsa import-req /tmp/server.req server

Then sign the request by running the easyrsa script with the sign-req option, followed by the request type and the common name. The request type can either be client or server, so for the OpenVPN server’s certificate request, be sure to use the server request type:

  • ./easyrsa sign-req server server

In the output, you’ll be asked to verify that the request comes from a trusted source. Type yes then press ENTER to confirm this:

You are about to sign the following certificate. Please check over the details shown below for accuracy. Note that this request has not been cryptographically verified. Please be sure it came from a trusted source or that you have verified the request checksum with the sender.  Request subject, to be signed as a server certificate for 1080 days:  subject=     commonName                = server   Type the word 'yes' to continue, or any other input to abort.   Confirm request details: yes 

If you encrypted your CA key, you’ll be prompted for your password at this point.

Next, transfer the signed certificate back to your VPN server using a secure method:

  • scp pki/issued/server.crt sammy@your_server_ip:/tmp

Before logging out of your CA machine, transfer the ca.crt file to your server as well:

  • scp pki/ca.crt sammy@your_server_ip:/tmp

Next, log back into your OpenVPN server and copy the server.crt and ca.crt files into your /etc/openvpn/ directory:

  • sudo cp /tmp/{server.crt,ca.crt} /etc/openvpn/

Then navigate to your EasyRSA directory:

  • cd EasyRSA-v3.0.6/

From there, create a strong Diffie-Hellman key to use during key exchange by typing:

  • ./easyrsa gen-dh

This may take a few minutes to complete. Once it does, generate an HMAC signature to strengthen the server’s TLS integrity verification capabilities:

  • sudo openvpn --genkey --secret ta.key

When the command finishes, copy the two new files to your /etc/openvpn/ directory:

  • sudo cp ~/EasyRSA-v3.0.6/ta.key /etc/openvpn/
  • sudo cp ~/EasyRSA-v3.0.6/pki/dh.pem /etc/openvpn/

With that, all the certificate and key files needed by your server have been generated. You’re ready to create the corresponding certificates and keys which your client machine will use to access your OpenVPN server.

Step 4 — Generating a Client Certificate and Key Pair

Although you can generate a private key and certificate request on your client machine and then send it to the CA to be signed, this guide outlines a process for generating the certificate request on the server. The benefit of this is that we can create a script which will automatically generate client configuration files that contain all of the required keys and certificates. This lets you avoid having to transfer keys, certificates, and configuration files to clients and streamlines the process of joining the VPN.

We will generate a single client key and certificate pair for this guide. If you have more than one client, you can repeat this process for each one. Please note, though, that you will need to pass a unique name value to the script for every client. Throughout this tutorial, the first certificate/key pair is referred to as client1.

Get started by creating a directory structure within your home directory to store the client certificate and key files:

  • mkdir -p ~/client-configs/keys

Since you will store your clients’ certificate/key pairs and configuration files in this directory, you should lock down its permissions now as a security measure:

  • chmod -R 700 ~/client-configs

Next, navigate back to the EasyRSA directory and run the easyrsa script with the gen-req and nopass options, along with the common name for the client:

  • cd ~/EasyRSA-v3.0.6/
  • ./easyrsa gen-req client1 nopass

Press ENTER to confirm the common name. Then, copy the client1.key file to the /client-configs/keys/ directory you created earlier:

  • cp pki/private/client1.key ~/client-configs/keys/

Next, transfer the client1.req file to your CA machine using a secure method:

  • scp pki/reqs/client1.req sammy@your_CA_ip:/tmp

Log in to your CA machine, navigate to the EasyRSA directory, and import the certificate request:

  • ssh sammy@your_CA_ip
  • cd EasyRSA-v3.0.6/
  • ./easyrsa import-req /tmp/client1.req client1

Then sign the request as you did for the server in the previous step. This time, though, be sure to specify the client request type:

  • ./easyrsa sign-req client client1

At the prompt, enter yes to confirm that you intend to sign the certificate request and that it came from a trusted source:

Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes

Again, if you encrypted your CA key, you’ll be prompted for your password here.

This will create a client certificate file named client1.crt. Transfer this file back to the server:

  • scp pki/issued/client1.crt sammy@your_server_ip:/tmp

SSH back into your OpenVPN server and copy the client certificate to the /client-configs/keys/ directory:

  • cp /tmp/client1.crt ~/client-configs/keys/

Next, copy the ca.crt and ta.key files to the /client-configs/keys/ directory as well:

  • sudo cp ~/EasyRSA-v3.0.6/ta.key ~/client-configs/keys/
  • sudo cp /etc/openvpn/ca.crt ~/client-configs/keys/

With that, your server and client’s certificates and keys have all been generated and are stored in the appropriate directories on your server. There are still a few actions that need to be performed with these files, but those will come in a later step. For now, you can move on to configuring OpenVPN on your server.

Step 5 — Configuring the OpenVPN Service

Now that both your client and server’s certificates and keys have been generated, you can begin configuring the OpenVPN service to use these credentials.

Start by copying a sample OpenVPN configuration file into the configuration directory and then extract it in order to use it as a basis for your setup:

  • sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
  • sudo gzip -d /etc/openvpn/server.conf.gz

Open the server configuration file in your preferred text editor:

  • sudo nano /etc/openvpn/server.conf

Find the HMAC section by looking for the tls-auth directive. This line should already be uncommented, but if isn’t then remove the “;” to uncomment it. Below this line, add the key-direction parameter, set to “0”:

tls-auth ta.key 0 # This file is secret key-direction 0 

Next, find the section on cryptographic ciphers by looking for the commented out cipher lines. The AES-256-CBC cipher offers a good level of encryption and is well supported. Again, this line should already be uncommented, but if it isn’t then just remove the “;” preceding it:

cipher AES-256-CBC 

Below this, add an auth directive to select the HMAC message digest algorithm. For this, SHA256 is a good choice:

auth SHA256 

Next, find the line containing a dh directive which defines the Diffie-Hellman parameters. Because of some recent changes made to EasyRSA, the filename for the Diffie-Hellman key may be different than what is listed in the example server configuration file. If necessary, change the file name listed here by removing the 2048 so it aligns with the key you generated in the previous step:

dh dh.pem 

Finally, find the user and group settings and remove the “;” at the beginning of each to uncomment these lines:

user nobody group nogroup 

The changes you’ve made to the sample server.conf file up to this point are necessary in order for OpenVPN to function. The changes outlined below are optional, though they too are needed for many common use cases.

(Optional) Push DNS Changes to Redirect All Traffic Through the VPN

The settings above will create the VPN connection between the two machines, but will not force any connections to use the tunnel. If you wish to use the VPN to route all of your traffic, you will likely want to push the DNS settings to the client computers.

There are a few directives in the server.conf file which you must change in order to enable this functionality. Find the redirect-gateway section and remove the semicolon “;” from the beginning of the redirect-gateway line to uncomment it:

push "redirect-gateway def1 bypass-dhcp" 

Just below this, find the dhcp-option section. Again, remove the “;” from in front of both of the lines to uncomment them:

push "dhcp-option DNS" push "dhcp-option DNS" 

This will assist clients in reconfiguring their DNS settings to use the VPN tunnel for as the default gateway.

(Optional) Adjust the Port and Protocol

By default, the OpenVPN server uses port 1194 and the UDP protocol to accept client connections. If you need to use a different port because of restrictive network environments that your clients might be in, you can change the port option. If you are not hosting web content on your OpenVPN server, port 443 is a popular choice since it is usually allowed through firewall rules.

# Optional! port 443 

Oftentimes, the protocol is restricted to that port as well. If so, change proto from UDP to TCP:

# Optional! proto tcp 

If you do switch the protocol to TCP, you will need to change the explicit-exit-notify directive’s value from 1 to 0, as this directive is only used by UDP. Failing to do so while using TCP will cause errors when you start the OpenVPN service:

# Optional! explicit-exit-notify 0 

If you have no need to use a different port and protocol, it is best to leave these two settings as their defaults.

(Optional) Point to Non-Default Credentials

If you selected a different name during the ./build-key-server command earlier, modify the cert and key lines that you see to point to the appropriate .crt and .key files. If you used the default name, “server”, this is already set correctly:

cert server.crt key server.key 

When you are finished, save and close the file.

After going through and making whatever changes to your server’s OpenVPN configuration are required for your specific use case, you can begin making some changes to your server’s networking.

Step 6 — Adjusting the Server Networking Configuration

There are some aspects of the server’s networking configuration that need to be tweaked so that OpenVPN can correctly route traffic through the VPN. The first of these is IP forwarding, a method for determining where IP traffic should be routed. This is essential to the VPN functionality that your server will provide.

Adjust your server’s default IP forwarding setting by modifying the /etc/sysctl.conf file:

  • sudo nano /etc/sysctl.conf

Inside, look for the commented line that sets net.ipv4.ip_forward. Remove the “#” character from the beginning of the line to uncomment this setting:


Save and close the file when you are finished.

To read the file and adjust the values for the current session, type:

  • sudo sysctl -p
net.ipv4.ip_forward = 1

If you followed the Debian 10 initial server setup guide listed in the prerequisites, you should have a UFW firewall in place. Regardless of whether you use the firewall to block unwanted traffic (which you almost always should do), for this guide you need a firewall to manipulate some of the traffic coming into the server. Some of the firewall rules must be modified to enable masquerading, an iptables concept that provides on-the-fly dynamic network address translation (NAT) to correctly route client connections.

Before opening the firewall configuration file to add the masquerading rules, you must first find the public network interface of your machine. To do this, type:

  • ip route | grep default

Your public interface is the string found within this command’s output that follows the word “dev”. For example, this result shows the interface named wlp11s0, which is highlighted below:

default via dev eth0 proto static

When you have the interface associated with your default route, open the /etc/ufw/before.rules file to add the relevant configuration:

  • sudo nano /etc/ufw/before.rules

UFW rules are typically added using the ufw command. Rules listed in the before.rules file, though, are read and put into place before the conventional UFW rules are loaded. Towards the top of the file, add the highlighted lines below. This will set the default policy for the POSTROUTING chain in the nat table and masquerade any traffic coming from the VPN. Remember to replace wlp11s0 in the -A POSTROUTING line below with the interface you found in the above command:

# # rules.before # # Rules that should be run before the ufw command line added rules. Custom # rules should be added to one of these chains: #   ufw-before-input #   ufw-before-output #   ufw-before-forward #  # START OPENVPN RULES # NAT table rules *nat :POSTROUTING ACCEPT [0:0]  # Allow traffic from OpenVPN client to eth0 (change to the interface you discovered!) -A POSTROUTING -s -o eth0 -j MASQUERADE COMMIT # END OPENVPN RULES  # Don't delete these required lines, otherwise there will be errors *filter . . . 

Save and close the file when you are finished.

Next, you need to tell UFW to allow forwarded packets by default as well. To do this, open the /etc/default/ufw file:

  • sudo nano /etc/default/ufw

Inside, find the DEFAULT_FORWARD_POLICY directive and change the value from DROP to ACCEPT:


Save and close the file when you are finished.

Next, adjust the firewall itself to allow traffic to OpenVPN. If you did not change the port and protocol in the /etc/openvpn/server.conf file, you will need to open up UDP traffic to port 1194. If you modified the port and/or protocol, substitute the values you selected here.

Also, in case you didn’t add the SSH port when completing the prerequisite tutorial, add it here as well:

  • sudo ufw allow 1194/udp
  • sudo ufw allow OpenSSH

After adding those rules, disable and re-enable UFW to restart it and load the changes from all of the files you’ve modified:

  • sudo ufw disable
  • sudo ufw enable

Your server is now configured to correctly handle OpenVPN traffic.

Step 7 — Starting and Enabling the OpenVPN Service

You’re finally ready to start the OpenVPN service on your server. This is done using the systemd utility systemctl.

Start the OpenVPN server by specifying your configuration file name as an instance variable after the systemd unit file name. The configuration file for your server is called /etc/openvpn/server.conf, so add @server to end of your unit file when calling it:

  • sudo systemctl start openvpn@server

Double-check that the service has started successfully by typing:

  • sudo systemctl status openvpn@server

If everything went well, your output will look something like this:

● openvpn@server.service - OpenVPN connection to server Loaded: loaded (/lib/systemd/system/openvpn@.service; disabled; vendor preset: enabled) Active: active (running) since Wed 2019-07-17 03:39:24 UTC; 29s ago Docs: man:openvpn(8) Main PID: 3371 (openvpn) Status: "Initialization Sequence Completed" Tasks: 1 (limit: 3587) Memory: 1.2M CGroup: /system.slice/system-openvpn.slice/openvpn@server.service └─3371 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --config /etc/openvpn/server.conf --writepid /run/openvpn/

You can also check that the OpenVPN tun0 interface is available by typing:

  • ip addr show tun0

This will output a configured interface:

3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100 link/none inet peer scope global tun0 valid_lft forever preferred_lft forever inet6 fe80::dd60:3a78:b0ca:1659/64 scope link stable-privacy valid_lft forever preferred_lft forever

After starting the service, enable it so that it starts automatically at boot:

  • sudo systemctl enable openvpn@server

Your OpenVPN service is now up and running. Before you can start using it, though, you must first create a configuration file for the client machine. This tutorial already went over how to create certificate/key pairs for clients, and in the next step we will demonstrate how to create an infrastructure that will generate client configuration files easily.

Step 8 — Creating the Client Configuration Infrastructure

Creating configuration files for OpenVPN clients can be somewhat involved, as every client must have its own config and each must align with the settings outlined in the server’s configuration file. Rather than writing a single configuration file that can only be used on one client, this step outlines a process for building a client configuration infrastructure which you can use to generate config files on-the-fly. You will first create a “base” configuration file then build a script which will allow you to generate unique client config files, certificates, and keys as needed.

Get started by creating a new directory where you will store client configuration files within the client-configs directory you created earlier:

  • mkdir -p ~/client-configs/files

Next, copy an example client configuration file into the client-configs directory to use as your base configuration:

  • cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf

Open this new file in your text editor:

  • nano ~/client-configs/base.conf

Inside, locate the remote directive. This points the client to your OpenVPN server address — the public IP address of your OpenVPN server. If you decided to change the port that the OpenVPN server is listening on, you will also need to change 1194 to the port you selected:

. . . # The hostname/IP and port of the server. # You can have multiple remote entries # to load balance between the servers. remote your_server_ip 1194 . . . 

Be sure that the protocol matches the value you are using in the server configuration:

proto udp 

Next, uncomment the user and group directives by removing the “;” at the beginning of each line:

# Downgrade privileges after initialization (non-Windows only) user nobody group nogroup 

Find the directives that set the ca, cert, and key. Comment out these directives since you will add the certs and keys within the file itself shortly:

# SSL/TLS parms. # See the server config file for more # description.  It's best to use # a separate .crt/.key file pair # for each client.  A single ca # file can be used for all clients. #ca ca.crt #cert client.crt #key client.key 

Similarly, comment out the tls-auth directive, as you will add ta.key directly into the client configuration file:

# If a tls-auth key is used on the server # then every client must also have the key. #tls-auth ta.key 1 

Mirror the cipher and auth settings that you set in the /etc/openvpn/server.conf file:

cipher AES-256-CBC auth SHA256 

Next, add the key-direction directive somewhere in the file. You must set this to “1” for the VPN to function correctly on the client machine:

key-direction 1 

Finally, add a few commented out lines. Although you can include these directives in every client configuration file, you only need to enable them for Linux clients that ship with an /etc/openvpn/update-resolv-conf file. This script uses the resolvconf utility to update DNS information for Linux clients.

# script-security 2 # up /etc/openvpn/update-resolv-conf # down /etc/openvpn/update-resolv-conf 

If your client is running Linux and has an /etc/openvpn/update-resolv-conf file, uncomment these lines from the client’s configuration file after it has been generated.

Save and close the file when you are finished.

Next, create a simple script that will compile your base configuration with the relevant certificate, key, and encryption files and then place the generated configuration in the ~/client-configs/files directory. Open a new file called within the ~/client-configs directory:

  • nano ~/client-configs/

Inside, add the following content, making sure to change sammy to that of your server’s non-root user account:

#!/bin/bash  # First argument: Client identifier  KEY_DIR=/home/sammy/client-configs/keys OUTPUT_DIR=/home/sammy/client-configs/files BASE_CONFIG=/home/sammy/client-configs/base.conf  cat $  {BASE_CONFIG} \     <(echo -e '<ca>') \     $  {KEY_DIR}/ca.crt \     <(echo -e '</ca>\n<cert>') \     $  {KEY_DIR}/$  {1}.crt \     <(echo -e '</cert>\n<key>') \     $  {KEY_DIR}/$  {1}.key \     <(echo -e '</key>\n<tls-auth>') \     $  {KEY_DIR}/ta.key \     <(echo -e '</tls-auth>') \     > $  {OUTPUT_DIR}/$  {1}.ovpn 

Save and close the file when you are finished.

Before moving on, be sure to mark this file as executable by typing:

  • chmod 700 ~/client-configs/

This script will make a copy of the base.conf file you made, collect all the certificate and key files you’ve created for your client, extract their contents, append them to the copy of the base configuration file, and export all of this content into a new client configuration file. This means that, rather than having to manage the client’s configuration, certificate, and key files separately, all the required information is stored in one place. The benefit of this is that if you ever need to add a client in the future, you can just run this script to quickly create the config file and ensure that all the important information is stored in a single, easy-to-access location.

Please note that any time you add a new client, you will need to generate new keys and certificates for it before you can run this script and generate its configuration file. You will get some practice using this script in the next step.

Step 9 — Generating Client Configurations

If you followed along with the guide, you created a client certificate and key named client1.crt and client1.key, respectively, in Step 4. You can generate a config file for these credentials by moving into your ~/client-configs directory and running the script you made at the end of the previous step:

  • cd ~/client-configs
  • sudo ./ client1

This will create a file named client1.ovpn in your ~/client-configs/files directory:

  • ls ~/client-configs/files

You need to transfer this file to the device you plan to use as the client. For instance, this could be your local computer or a mobile device.

While the exact applications used to accomplish this transfer will depend on your device’s operating system and your personal preferences, a dependable and secure method is to use SFTP (SSH file transfer protocol) or SCP (Secure Copy) on the backend. This will transport your client’s VPN authentication files over an encrypted connection.

Here is an example SFTP command using the client1.ovpn example which you can run from your local computer (macOS or Linux). It places the .ovpn file in your home directory:

  • sftp sammy@your_server_ip:client-configs/files/client1.ovpn ~/

Here are several tools and tutorials for securely transferring files from the server to a local computer:

Step 10 — Installing the Client Configuration

This section covers how to install a client VPN profile on Windows, macOS, Linux, iOS, and Android. None of these client instructions are dependent on one another, so feel free to skip to whichever is applicable to your device.

The OpenVPN connection will have the same name as whatever you called the .ovpn file. In regards to this tutorial, this means that the connection is named client1.ovpn, aligning with the first client file you generated.



Download the OpenVPN client application for Windows from OpenVPN’s Downloads page. Choose the appropriate installer version for your version of Windows.

Note: OpenVPN needs administrative privileges to install.

After installing OpenVPN, copy the .ovpn file to:

C:\Program Files\OpenVPN\config 

When you launch OpenVPN, it will automatically see the profile and make it available.

You must run OpenVPN as an administrator each time it’s used, even by administrative accounts. To do this without having to right-click and select Run as administrator every time you use the VPN, you must preset this from an administrative account. This also means that standard users will need to enter the administrator’s password to use OpenVPN. On the other hand, standard users can’t properly connect to the server unless the OpenVPN application on the client has admin rights, so the elevated privileges are necessary.

To set the OpenVPN application to always run as an administrator, right-click on its shortcut icon and go to Properties. At the bottom of the Compatibility tab, click the button to Change settings for all users. In the new window, check Run this program as an administrator.


Each time you launch the OpenVPN GUI, Windows will ask if you want to allow the program to make changes to your computer. Click Yes. Launching the OpenVPN client application only puts the applet in the system tray so that you can connect and disconnect the VPN as needed; it does not actually make the VPN connection.

Once OpenVPN is started, initiate a connection by going into the system tray applet and right-clicking on the OpenVPN applet icon. This opens the context menu. Select client1 at the top of the menu (that’s your client1.ovpn profile) and choose Connect.

A status window will open showing the log output while the connection is established, and a message will show once the client is connected.

Disconnect from the VPN the same way: Go into the system tray applet, right-click the OpenVPN applet icon, select the client profile and click Disconnect.



Tunnelblick is a free, open source OpenVPN client for macOS. You can download the latest disk image from the Tunnelblick Downloads page. Double-click the downloaded .dmg file and follow the prompts to install.

Towards the end of the installation process, Tunnelblick will ask if you have any configuration files. Answer I have configuration files and let Tunnelblick finish. Open a Finder window and double-click client1.ovpn. Tunnelblick will install the client profile. Administrative privileges are required.


Launch Tunnelblick by double-clicking the Tunnelblick icon in the Applications folder. Once Tunnelblick has been launched, there will be a Tunnelblick icon in the menu bar at the top right of the screen for controlling connections. Click on the icon, and then the Connect client1 menu item to initiate the VPN connection.



If you are using Linux, there are a variety of tools that you can use depending on your distribution. Your desktop environment or window manager might also include connection utilities.

The most universal way of connecting, however, is to just use the OpenVPN software.

On Debian, you can install it just as you did on the server by typing:

  • sudo apt update
  • sudo apt install openvpn

On CentOS you can enable the EPEL repositories and then install it by typing:

  • sudo yum install epel-release
  • sudo yum install openvpn


Check to see if your distribution includes an /etc/openvpn/update-resolv-conf script:

  • ls /etc/openvpn

Next, edit the OpenVPN client configuration file you transfered:

  • nano client1.ovpn

If you were able to find an update-resolv-conf file, uncomment the three lines you added to adjust the DNS settings:

script-security 2 up /etc/openvpn/update-resolv-conf down /etc/openvpn/update-resolv-conf 

If you are using CentOS, change the group directive from nogroup to nobody to match the distribution’s available groups:

group nobody 

Save and close the file.

Now, you can connect to the VPN by just pointing the openvpn command to the client configuration file:

  • sudo openvpn --config client1.ovpn

This should connect you to your VPN.



From the iTunes App Store, search for and install OpenVPN Connect, the official iOS OpenVPN client application. To transfer your iOS client configuration onto the device, connect it directly to a computer.

The process of completing the transfer with iTunes is outlined here. Open iTunes on the computer and click on iPhone > apps. Scroll down to the bottom to the File Sharing section and click the OpenVPN app. The blank window to the right, OpenVPN Documents, is for sharing files. Drag the .ovpn file to the OpenVPN Documents window.

iTunes showing the VPN profile ready to load on the iPhone

Now launch the OpenVPN app on the iPhone. You will receive a notification that a new profile is ready to import. Tap the green plus sign to import it.

The OpenVPN iOS app showing new profile ready to import


OpenVPN is now ready to use with the new profile. Start the connection by sliding the Connect button to the On position. Disconnect by sliding the same button to Off.

Note: The VPN switch under Settings cannot be used to connect to the VPN. If you try, you will receive a notice to only connect using the OpenVPN app.

The OpenVPN iOS app connected to the VPN



Open the Google Play Store. Search for and install Android OpenVPN Connect, the official Android OpenVPN client application.

You can transfer the .ovpn profile by connecting the Android device to your computer by USB and copying the file over. Alternatively, if you have an SD card reader, you can remove the device’s SD card, copy the profile onto it and then insert the card back into the Android device.

Start the OpenVPN app and tap the menu to import the profile.

The OpenVPN Android app profile import menu selection

Then navigate to the location of the saved profile (the screenshot uses /sdcard/Download/) and select the file. The app will make a note that the profile was imported.

The OpenVPN Android app selecting VPN profile to import


To connect, simply tap the Connect button. You’ll be asked if you trust the OpenVPN application. Choose OK to initiate the connection. To disconnect from the VPN, go back to the OpenVPN app and choose Disconnect.

The OpenVPN Android app ready to connect to the VPN

Step 11 — Testing Your VPN Connection (Optional)

Note: This method for testing your VPN connection will only work if you opted to route all your traffic through the VPN in Step 5.

Once everything is installed, a simple check confirms everything is working properly. Without having a VPN connection enabled, open a browser and go to DNSLeakTest.

The site will return the IP address assigned by your internet service provider and as you appear to the rest of the world. To check your DNS settings through the same website, click on Extended Test and it will tell you which DNS servers you are using.

Now connect the OpenVPN client to your Droplet’s VPN and refresh the browser. A completely different IP address (that of your VPN server) should now appear, and this is how you appear to the world. Again, DNSLeakTest’s Extended Test will check your DNS settings and confirm you are now using the DNS resolvers pushed by your VPN.

Step 12 — Revoking Client Certificates

Occasionally, you may need to revoke a client certificate to prevent further access to the OpenVPN server.

To do so, navigate to the EasyRSA directory on your CA machine:

  • cd EasyRSA-v3.0.6/

Next, run the easyrsa script with the revoke option, followed by the client name you wish to revoke:

  • ./easyrsa revoke client2

This will ask you to confirm the revocation by entering yes:

Please confirm you wish to revoke the certificate with the following subject: subject= commonName = client2 Type the word 'yes' to continue, or any other input to abort. Continue with revocation: yes

After confirming the action, the CA will fully revoke the client’s certificate. However, your OpenVPN server currently has no way to check whether any clients’ certificates have been revoked and the client will still have access to the VPN. To correct this, create a certificate revocation list (CRL) on your CA machine:

  • ./easyrsa gen-crl

This will generate a file called crl.pem. Securely transfer this file to your OpenVPN server:

  • scp ~/EasyRSA-v3.0.6/pki/crl.pem sammy@your_server_ip:/tmp

On your OpenVPN server, copy this file into your /etc/openvpn/ directory:

  • sudo cp /tmp/crl.pem /etc/openvpn

Next, open the OpenVPN server configuration file:

  • sudo nano /etc/openvpn/server.conf

At the bottom of the file, add the crl-verify option, which will instruct the OpenVPN server to check the certificate revocation list that we’ve created each time a connection attempt is made:

crl-verify crl.pem 

Save and close the file.

Finally, restart OpenVPN to implement the certificate revocation:

  • sudo systemctl restart openvpn@server

The client should no longer be able to successfully connect to the server using the old credential.

To revoke additional clients, follow this process:

  1. Revoke the certificate with the ./easyrsa revoke client_name command
  2. Generate a new CRL
  3. Transfer the new crl.pem file to your OpenVPN server and copy it to the /etc/openvpn directory to overwrite the old list.
  4. Restart the OpenVPN service.

You can use this process to revoke any certificates that you’ve previously issued for your server.


You are now securely traversing the internet protecting your identity, location, and traffic from snoopers and censors.

To configure more clients, you only need to follow steps 4 and 9-11 for each additional device. To revoke access to clients, just follow step 12.

DigitalOcean Community Tutorials

How To Install the Apache Web Server on Debian 10


The Apache HTTP server is the most widely-used web server in the world. It provides many powerful features including dynamically loadable modules, robust media support, and extensive integration with other popular software.

In this guide, we’ll explain how to install an Apache web server on your Debian 10 server.


Before you begin this guide, you should have a regular, non-root user with sudo privileges configured on your server. Additionally, you will need to enable a basic firewall to block non-essential ports. You can learn how to configure a regular user account and set up a firewall for your server by following our initial server setup guide for Debian 10.

When you have an account available, log in as your non-root user to begin.

Step 1 — Installing Apache

Apache is available within Debian’s default software repositories, making it possible to install it using conventional package management tools.

Let’s begin by updating the local package index to reflect the latest upstream changes:

  • sudo apt update

Then, install the apache2 package:

  • sudo apt install apache2

After confirming the installation, apt will install Apache and all required dependencies.

Step 2 — Adjusting the Firewall

Before testing Apache, it’s necessary to modify the firewall settings to allow outside access to the default web ports. Assuming that you followed the instructions in the prerequisites, you should have a UFW firewall configured to restrict access to your server.

During installation, Apache registers itself with UFW to provide a few application profiles that can be used to enable or disable access to Apache through the firewall.

List the ufw application profiles by typing:

  • sudo ufw app list

You will see a list of the application profiles:

Available applications: AIM Bonjour CIFS . . . WWW WWW Cache WWW Full WWW Secure . . .

The Apache profiles begin with WWW:

  • WWW: This profile opens only port 80 (normal, unencrypted web traffic)
  • WWW Cache: This profile opens only port 8080 (sometimes used for caching and web proxies)
  • WWW Full: This profile opens both port 80 (normal, unencrypted web traffic) and port 443 (TLS/SSL encrypted traffic)
  • WWW Secure: This profile opens only port 443 (TLS/SSL encrypted traffic)

It is recommended that you enable the most restrictive profile that will still allow the traffic you’ve configured. Since we haven’t configured SSL for our server yet in this guide, we will only need to allow traffic on port 80:

  • sudo ufw allow 'WWW'

You can verify the change by typing:

  • sudo ufw status

You should see HTTP traffic allowed in the displayed output:

Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere WWW ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) WWW (v6) ALLOW Anywhere (v6)

As you can see, the profile has been activated to allow access to the web server.

Step 3 — Checking your Web Server

At the end of the installation process, Debian 10 starts Apache. The web server should already be up and running.

Check with the systemd init system to make sure the service is running by typing:

  • sudo systemctl status apache2
● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2019-07-19 15:33:01 UTC; 4min 13s ago Docs: . . . Jul 19 15:33:01 debssh systemd[1]: Starting The Apache HTTP Server... Jul 19 15:33:01 debssh apachectl[2791]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using Set the 'ServerName' directive global Jul 19 15:33:01 debssh systemd[1]: Started The Apache HTTP Server.

As you can see from this output, the service appears to have started successfully. However, the best way to test this is to request a page from Apache.

You can access the default Apache landing page to confirm that the software is running properly through your IP address. If you do not know your server’s IP address, you can get it a few different ways from the command line.

Try typing this at your server’s command prompt:

  • hostname -I

You will get back a few addresses separated by spaces. You can try each in your web browser to see if they work.

An alternative is using the curl tool, which should give you your public IP address as seen from another location on the internet.

First, install curl using apt:

  • sudo apt install curl

Then, use curl to retrieve using IPv4:

  • curl -4

When you have your server’s IP address, enter it into your browser’s address bar:


You should see the default Debian 10 Apache web page:

Apache default page

This page indicates that Apache is working correctly. It also includes some basic information about important Apache files and directory locations.

Step 4 — Managing the Apache Process

Now that you have your web server up and running, let’s go over some basic management commands.

To stop your web server, type:

  • sudo systemctl stop apache2

To start the web server when it is stopped, type:

  • sudo systemctl start apache2

To stop and then start the service again, type:

  • sudo systemctl restart apache2

If you are simply making configuration changes, Apache can often reload without dropping connections. To do this, use this command:

  • sudo systemctl reload apache2

By default, Apache is configured to start automatically when the server boots. If this is not what you want, disable this behavior by typing:

  • sudo systemctl disable apache2

To re-enable the service to start up at boot, type:

  • sudo systemctl enable apache2

Apache should now start automatically when the server boots again.

When using the Apache web server, you can use virtual hosts (similar to server blocks in Nginx) to encapsulate configuration details and host more than one domain from a single server. In the following commands, replace your_domain with your own domain name. To learn more about setting up a domain name with DigitalOcean, see our Introduction to DigitalOcean DNS.

Apache on Debian 10 has one server block enabled by default that is configured to serve documents from the /var/www/html directory. While this works well for a single site, it can become unwieldy if you are hosting multiple sites. Instead of modifying /var/www/html, let’s create a directory structure within /var/www for our your_domain site, leaving /var/www/html in place as the default directory to be served if a client request doesn’t match any other sites.

Create the directory for your_domain as follows, using the -p flag to create any necessary parent directories:

sudo mkdir -p /var/www/your_domain/html 

Next, assign ownership of the directory with the $ USER environmental variable:

  • sudo chown -R $ USER:$ USER /var/www/your_domain/html

The permissions of your web roots should be correct if you haven’t modified your unmask value, but you can make sure by typing:

  • sudo chmod -R 755 /var/www/your_domain

Next, create a sample index.html page using nano or your favorite editor:

  • nano /var/www/your_domain/html/index.html

Inside, add the following sample HTML:

<html>     <head>         <title>Welcome to your_domain!</title>     </head>     <body>         <h1>Success!  The your_domain virtual host is working!</h1>     </body> </html> 

Save and close the file when you are finished.

In order for Apache to serve this content, it’s necessary to create a virtual host file with the correct directives. Instead of modifying the default configuration file located at /etc/apache2/sites-available/000-default.conf directly, let’s make a new one at /etc/apache2/sites-available/your_domain.conf:

  • sudo nano /etc/apache2/sites-available/your_domain.conf

Paste in the following configuration block, which is similar to the default, but updated for our new directory and domain name:

<VirtualHost *:80>     ServerAdmin admin@your_email_domain     ServerName your_domain     ServerAlias www.your_domain     DocumentRoot /var/www/your_domain/html     ErrorLog $  {APACHE_LOG_DIR}/error.log     CustomLog $  {APACHE_LOG_DIR}/access.log combined </VirtualHost> 

Notice that we’ve updated the DocumentRoot to our new directory and ServerAdmin to an email that the your_domain site administrator can access. We’ve also added two directives: ServerName, which establishes the base domain that should match for this virtual host definition, and ServerAlias, which defines further names that should match as if they were the base name.

Save and close the file when you are finished.

Let’s enable the file with the a2ensite tool:

  • sudo a2ensite your_domain.conf

Disable the default site defined in 000-default.conf:

  • sudo a2dissite 000-default.conf

Next, let’s test for configuration errors:

  • sudo apache2ctl configtest

You should see the following output:

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using Set the 'ServerName' directive globally to suppress this message Syntax OK

Restart Apache to implement your changes:

  • sudo systemctl restart apache2

Apache should now be serving your domain name. You can test this by navigating to http://your_domain, where you should see something like this:

Apache virtual host example

Step 6 – Getting Familiar with Important Apache Files and Directories

Now that you know how to manage the Apache service itself, you should take a few minutes to familiarize yourself with a few important directories and files.


  • /var/www/html: The actual web content, which by default only consists of the default Apache page you saw earlier, is served out of the /var/www/html directory. This can be changed by altering Apache configuration files.

Server Configuration

  • /etc/apache2: The Apache configuration directory. All of the Apache configuration files reside here.
  • /etc/apache2/apache2.conf: The main Apache configuration file. This can be modified to make changes to the Apache global configuration. This file is responsible for loading many of the other files in the configuration directory.
  • /etc/apache2/ports.conf: This file specifies the ports that Apache will listen on. By default, Apache listens on port 80 and additionally listens on port 443 when a module providing SSL capabilities is enabled.
  • /etc/apache2/sites-available/: The directory where per-site virtual hosts can be stored. Apache will not use the configuration files found in this directory unless they are linked to the sites-enabled directory. Typically, all server block configuration is done in this directory, and then enabled by linking to the other directory with the a2ensite command.
  • /etc/apache2/sites-enabled/: The directory where enabled per-site virtual hosts are stored. Typically, these are created by linking to configuration files found in the sites-available directory with the a2ensite. Apache reads the configuration files and links found in this directory when it starts or reloads to compile a complete configuration.
  • /etc/apache2/conf-available/, /etc/apache2/conf-enabled/: These directories have the same relationship as the sites-available and sites-enabled directories, but are used to store configuration fragments that do not belong in a virtual host. Files in the conf-available directory can be enabled with the a2enconf command and disabled with the a2disconf command.
  • /etc/apache2/mods-available/, /etc/apache2/mods-enabled/: These directories contain the available and enabled modules, respectively. Files in ending in .load contain fragments to load specific modules, while files ending in .conf contain the configuration for those modules. Modules can be enabled and disabled using the a2enmod and a2dismod command.

Server Logs

  • /var/log/apache2/access.log: By default, every request to your web server is recorded in this log file unless Apache is configured to do otherwise.
  • /var/log/apache2/error.log: By default, all errors are recorded in this file. The LogLevel directive in the Apache configuration specifies how much detail the error logs will contain.


Now that you have your web server installed, you have many options for the type of content you can serve and the technologies you can use to create a richer experience.

If you’d like to build out a more complete application stack, you can look at this article on how to configure a LAMP stack on Debian 10.

DigitalOcean Community Tutorials

Initial Server Setup with Debian 10


When you first create a new Debian 10 server, there are a few configuration steps that you should take early on as part of the basic setup. This will increase the security and usability of your server and will give you a solid foundation for subsequent actions.

In this tutorial, we will learn how to log into our server as the root user, create a new user with admin privileges, and set up a basic firewall.

Step 1 — Logging in as Root

To log into your server, you will need to know your server’s public IP address. You will also need the password or, if you installed an SSH key for authentication, the private key for the root user’s account. If you have not already logged into your server, you may want to follow our guide on how to connect to your Droplet with SSH, which covers this process in detail.

If you are not already connected to your server, go ahead and log in as the root user using the following command (substitute the highlighted portion of the command with your server’s public IP address):

  • ssh root@your_server_ip

Accept the warning about host authenticity if it appears. If you are using password authentication, provide your root password to log in. If you are using an SSH key that is passphrase protected, you may be prompted to enter the passphrase the first time you use the key each session. If this is your first time logging into the server with a password, you may also be prompted to change the root password.

About Root

The root user is the administrative user in a Linux environment that has very broad privileges. Because of the heightened privileges of the root account, you are discouraged from using it on a regular basis. This is because part of the power inherent with the root account is the ability to make very destructive changes, even by accident.

The next step is to set up an alternative user account with a reduced scope of influence for day-to-day work. Later, we’ll explain how to gain increased privileges for those times when you need them.

Step 2 — Creating a New User

Once you are logged in as root, we’re prepared to add the new user account that we will use to log in from now on.

This example creates a new user called sammy, but you should replace it with a username that you like:

  • adduser sammy

You will be asked a few questions, starting with the account password.

Enter a strong password and, optionally, fill in any of the additional information you would like. This is not required and you can just hit ENTER in any field you wish to skip.

Next, we’ll set up this new user with admin privileges.

Step 3 — Granting Administrative Privileges

Now, we have created a new user account with regular account privileges. However, we may sometimes need to do administrative tasks with it.

To avoid having to log out of our normal user and log back in as the root account, we can set up what is known as superuser or root privileges for our normal account. This will allow our normal user to run commands with administrative privileges by putting the word sudo before the command.

To add these privileges to our new user, we need to add the new user to the sudo group. By default, on Debian 10, users who belong to the sudo group are allowed to use the sudo command.

As root, run this command to add your new user to the sudo group (substitute the highlighted word with your new user):

  • usermod -aG sudo sammy

Now, when logged in as your regular user, you can type sudo before commands to run the command with superuser privileges.

Step 4 — Setting Up a Basic Firewall

Debian servers can use firewalls to make sure only certain connections to specific services are allowed. In this guide, we will install and use the UFW firewall to help set firewall policies and manage exceptions.

We can use the apt package manager to install UFW. Update the local index to retrieve the latest information about available packages and then install the UFW firewall software by typing:

  • apt update
  • apt install ufw

Note: If your servers are running on DigitalOcean, you can optionally use DigitalOcean Cloud Firewalls instead of the UFW firewall. We recommend using only one firewall at a time to avoid conflicting rules that may be difficult to debug.

Firewall profiles allow UFW to manage named sets of firewall rules for installed applications. Profiles for some common software are bundled with UFW by default and packages can register additional profiles with UFW during the installation process. OpenSSH, the service allowing us to connect to our server now, has a firewall profile that we can use.

You list all available application profiles by typing:

  • ufw app list
Available applications: . . . OpenSSH . . .

We need to make sure that the firewall allows SSH connections so that we can log back in next time. We can allow these connections by typing:

  • ufw allow OpenSSH

Afterwards, we can enable the firewall by typing:

  • ufw enable

Type y and press ENTER to proceed. You can see that SSH connections are still allowed by typing:

  • ufw status
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6)

As the firewall is currently blocking all connections except for SSH, if you install and configure additional services, you will need to adjust the firewall settings to allow acceptable traffic in. You can learn some common UFW operations in our UFW essentials guide.

Step 5 — Enabling External Access for Your Regular User

Now that we have a regular user for daily use, we need to make sure we can SSH into the account directly.

Note: Until verifying that you can log in and use sudo with your new user, we recommend staying logged in as root. This way, if you have problems, you can troubleshoot and make any necessary changes as root. If you are using a DigitalOcean Droplet and experience problems with your root SSH connection, you can also log into the Droplet using the DigitalOcean Console.

The process for configuring SSH access for your new user depends on whether your server’s root account uses a password or SSH keys for authentication.

If the Root Account Uses Password Authentication

If you logged in to your root account using a password, then password authentication is enabled for SSH. You can SSH to your new user account by opening up a new terminal session and using SSH with your new username:

  • ssh sammy@your_server_ip

After entering your regular user’s password, you will be logged in. Remember, if you need to run a command with administrative privileges, type sudo before it like this:

  • sudo command_to_run

You will be prompted for your regular user password when using sudo for the first time each session (and periodically afterwards).

To enhance your server’s security, we strongly recommend setting up SSH keys instead of using password authentication. Follow our guide on setting up SSH keys on Debian 10 to learn how to configure key-based authentication.

If the Root Account Uses SSH Key Authentication

If you logged in to your root account using SSH keys, then password authentication is disabled for SSH. You will need to add a copy of your local public key to the new user’s ~/.ssh/authorized_keys file to log in successfully.

Since your public key is already in the root account’s ~/.ssh/authorized_keys file on the server, we can copy that file and directory structure to our new user account in our existing session with the cp command. Afterwards, we can adjust ownership of the files using the chown command.

Make sure to change the highlighted portions of the command below to match your regular user’s name:

  • cp -r ~/.ssh /home/sammy
  • chown -R sammy:sammy /home/sammy/.ssh

The cp -r command copies the entire directory to the new user’s home directory, and the chown -R command changes the owner of that directory (and everything inside it) to the specified username:groupname (Debian creates a group with the same name as your username by default).

Now, open up a new terminal session and log in via SSH with your new username:

  • ssh sammy@your_server_ip

You should be logged in to the new user account without using a password. Remember, if you need to run a command with administrative privileges, type sudo before it like this:

  • sudo command_to_run

You will be prompted for your regular user password when using sudo for the first time each session (and periodically afterwards).

Where To Go From Here?

At this point, you have a solid foundation for your server. You can install any of the software you need on your server now.

DigitalOcean Community Tutorials

How To Install and Configure Postfix as a Send-Only SMTP Server on Debian 10


Postfix is a mail transfer agent (MTA), an application used to send and receive email. In this tutorial, you will install and configure Postfix so that it can be used to send emails by local applications only — that is, those installed on the same server as Postfix.

Why would you want to do that?

If you’re already using a third-party email provider for sending and receiving emails, you do not need to run your own mail server. However, if you manage a cloud server on which you have installed applications that need to send email notifications, running a local, send-only SMTP server is a good alternative to using a third-party email service provider or running a full-blown SMTP server.

In this tutorial, you’ll install and configure Postfix as a send-only SMTP server on Debian 10.


To follow this tutorial, you will need:

Note that your server’s hostname should match your domain or subdomain. You can verify the server’s hostname by typing hostname at the command prompt. The output should match the name you gave the server when it was being created.

Step 1 — Installing Postfix

In this step, you’ll learn how to install Postfix. You will need two packages: mailutils, which includes programs necessary for Postfix to function, and postfix itself.

First, update the package database:

  • sudo apt update

Next, install mailtuils:

  • sudo apt install mailutils

Finally, install postfix:

  • sudo apt install postfix

Near the end of the installation process, you will be presented with a window that looks like the one in the image below:

Initial Config Screen

Press ENTER to continue.

The default option is Internet Site, which is preselected on the following screen:

Config Selection Screen

Press ENTER to continue.

After that, you’ll get another window to set the System mail name:

System Mail Name Selection

The System mail name should be the same as the name you assigned to the server when you were creating it. If it shows a subdomain like, change it to just When you’ve finished, press TAB, then ENTER.

You now have Postfix installed and are ready to modify its configuration settings.

Step 2 — Configuring Postfix

In this step, you’ll configure Postfix to process requests to send emails only from the server on which it is running, i.e. from localhost.

For that to happen, Postfix needs to be configured to listen only on the loopback interface, the virtual network interface that the server uses to communicate internally. To make the change, open the main Postfix configuration file using nano or your favorite text editor:

  • sudo nano /etc/postfix/

With the file open, scroll down until you see the following section:

. . . mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all . . . 

Change the line that reads inet_interfaces = all to inet_interfaces = loopback-only:

. . . mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = loopback-only . . . 

Another directive you’ll need to modify is mydestination, which is used to specify the list of domains that are delivered via the local_transport mail delivery transport. By default, the values are similar to these:

. . . mydestination = $ myhostname,,, , localhost . . .

The recommended defaults for this directive are given in the code block below, so modify yours to match:

. . . mydestination = $ myhostname, localhost.$ mydomain, $ mydomain . . .

Save and close the file.

Note: If you’re hosting multiple domains on a single server, the other domains can also be passed to Postfix using the mydestination directive. However, to configure Postfix in a manner that scales and that does not present issues for such a setup involves additional configurations that are beyond the scope of this article.

Finally, restart Postfix.

  • sudo systemctl restart postfix

Step 3 — Testing the SMTP Server

In this step, you’ll test whether Postfix can send emails to an external email account using the mail command, which is part of the mailutils package you installed in Step 1.

To send a test email, type:

  • echo "This is the body of the email" | mail -s "This is the subject line" your_email_address

In performing your own test(s), you may use the body and subject line text as-is, or change them to your liking. However, in place of your_email_address, use a valid email address. The domain can be,,, or any other email service provider that you use.

Now check the email address where you sent the test message. You should see the message in your Inbox. If not, check your Spam folder.

Note that with this configuration, the address in the From field for the test emails you send will be, where sammy is your Linux non-root username and the domain is the server’s hostname. If you change your username, the From address will also change.

Step 4 — Forwarding System Mail

The last thing we want to set up is forwarding, so you’ll get emails sent to root on the system at your personal, external email address.

To configure Postfix so that system-generated emails will be sent to your email address, you need to edit the /etc/aliases file. Open that file now:

  • sudo nano /etc/aliases

The full contents of the file on a default installation of Debian 10 are as follows:

mailer-daemon: postmaster postmaster: root nobody: root hostmaster: root usenet: root news: root webmaster: root www: root ftp: root abuse: root noc: root security: root 

The postmaster: root setting ensures that system-generated emails are sent to the root user. You want to edit these settings so these emails are rerouted to your email address. To accomplish that, add the following line below the postmaster: root setting:

mailer-daemon: postmaster postmaster:    root root:          your_email_address . . . 

Replace your_email_address with your personal email address. When finished, save and close the file. For the change to take effect, run the following command:

  • sudo newaliases

You can test that it works by sending an email to the root account using:

  • echo "This is the body of the email" | mail -s "This is the subject line" root

You should receive the email at your email address. If not, check your Spam folder.


That’s all it takes to set up a send-only email server using Postfix. You may want to take some additional steps to protect your domain from spammers, however.

If you want to receive notifications from your server at a single address, then having emails marked as Spam is less of an issue because you can create a whitelist workaround. However, if you want to send emails to potential site users (such as confirmation emails for a message board sign-up), you should definitely set up SPF records and DKIM so your server’s emails are more likely to be seen as legitimate.

If configured correctly, these steps make it difficult to send Spam with an address that appears to originate from your domain. Taking these additional configuration steps will also make it more likely for common mail providers to see emails from your server as legitimate.

DigitalOcean Community Tutorials

Zato Blog: Integrating with Microsoft SQL Server via stored procedures

This article will show you how to invoke MS SQL stored procedures from Zato services – a feature new in the just released version 3.1 of the Python-based integration platform.

In web-admin

Start off by installing the latest updates.

Next, the first thing needed is creation of a new outgoing SQL connection – make sure to choose the MS SQL (Direct) type, as below.

It is considered a direct one because, even though it is based on SQLAlchemy, it does not make use of the most of SQLAlchemy’s functionality and lets one invoke stored procedures alone, i.e. it is not possible to use this type of connections with ORM or anything else – only stored procedures are supported.

Make sure to change the password after creating a connection – the default one is a randomly generated string.

Python code

In most cases, to invoke a stored procedure, use the code below:

# -*- coding: utf-8 -*-   # Zato from zato.server.service import Service  class MyService(Service):     def handle(self):          # Connection to use         name = 'My MS SQL Connection'          conn = self.outgoing.sql.get(name)         session = conn.session()          # Procedure to invoke         proc_name = 'get_current_user'          # Arguments it has on input         args = ['']          data = session.callproc(proc_name, args)          # Data is a list of dictionaries, each of which         # represents a single row of data returned by the procedure.         for row in data:             ... 

Lazy evaluation

The usage example above will work in many cases but, supposing a procedure returns many thousands of rows, it may not be efficient to read them in all in a single call.

This would potentially create a big list of row elements – if all them are indeed required in a single place then this is not a concern. But if they should be processed one by one then it may be better to explicitly fetch and process a single row at a time.

To achieve it, use_yield=True can be applied, as in the code below. Now, each iteration of the for loop will return a new row, without ever accumulating all of them in RAM.

# -*- coding: utf-8 -*-   # Zato from zato.server.service import Service  class MyService(Service):     def handle(self):          # Connection to use         name = 'My MS SQL Connection'          conn = self.outgoing.sql.get(name)         session = conn.session()          # Procedure to invoke         proc_name = 'get_current_user'          # Arguments it has on input         args = ['']          data = session.callproc(proc_name, args, use_yield=True)          # Data is a Python generator now and each iteration         # of the loop returns a new row from the stored procedure.         for row in data:             ... 

Wrapping up

Ability to use MS SQL is a feature new in Zato 3.1 – it works in a way similar to other SQL connection types with the notable exception that only stored procedures can be invoked from Python code.

There are two ways to invoke stored procedures – either by reading the whole output into a service or processing rows one by one. The latter is recommended if a large number of rows is to be processed by the service.

Planet Python