# Security

# Overview

We automatically setup all services with several layers of security activated by default.  
  
This includes:

- [Automated SSL / TLS](https://docs.elest.io/books/security/page/custom-domain-and-automated-encryption-ssltls "Automated encryption (SSL/TLS)")
- [Network Firewall](https://docs.elest.io/books/security/page/network-firewall "Network Firewall")
- [IP Rate Limiter](https://docs.elest.io/books/security/page/ip-rate-limiter "IP rate limiter")
- [Output Cache](https://docs.elest.io/books/security/page/output-cache "Output cache")
- [Accidental termination protection &amp; Grace period](https://docs.elest.io/books/security/page/termination-protection-grace-period "Termination protection & grace period")
- [Manage SSH Keys](https://docs.elest.io/books/security/page/manage-ssh-keys "Manage SSH Keys")

Each of these features are accessible from your Dashboard via the *Security* tab.

[![Managed Service Dashboard.png](https://docs.elest.io/uploads/images/gallery/2022-09/managed-service-dashboard.png)](https://docs.elest.io/uploads/images/gallery/2022-01/image-1643091771191.png)

# Nginx advanced configuration

#### Edit the website nginx configuration

From the service overview screen it's possible to edit the nginx configuration for the elestio default subdomain domain &amp; custom domain, to do that go to the Security tab, then click on Nginx configuration then click on Config button.

[![image.png](https://docs.elest.io/uploads/images/gallery/2025-03/scaled-1680-/ELOimage.png)](https://docs.elest.io/uploads/images/gallery/2025-03/ELOimage.png)

There you will see the site configuration in nginx, you are able from there to add or remove headers, to configure the reverse proxy and much more. Nginx is very powerful and provide tons of customizations and control.

[![image.png](https://docs.elest.io/uploads/images/gallery/2025-03/scaled-1680-/XcBimage.png)](https://docs.elest.io/uploads/images/gallery/2025-03/XcBimage.png)

#### Edit the global Nginx configuration

It's also possible to edit the global nginx configuration, to do that follow those steps:

1\) create a file named **nginx.conf** in **/opt/elestio/nginx/**

2\) Paste exactly this content in the file, then you can customize if for your needs:

```

worker_processes auto;

worker_rlimit_nofile 100000;

events {
  worker_connections 4000;
}

http {
  include mime.types;
  default_type application/octet-stream;
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  server_tokens off;

  # reasonable defaults
  client_header_timeout 10m;
  client_body_timeout 10m;
  send_timeout 10m;
  client_max_body_size 5120M;

  connection_pool_size 256;
  client_header_buffer_size 32k;
  large_client_header_buffers 4 64k;
  request_pool_size 4k;
  
  server_names_hash_bucket_size 4096;

  output_buffers 1 32k;
  postpone_output 1460;

  proxy_buffer_size   128k;
  proxy_buffers   4 256k;
  proxy_busy_buffers_size   256k;

  ignore_invalid_headers on;

  # enable gzip support
  include server-gzip.conf;

  # auto-ssl lua magic for automatic generation of certs
  include resty-http.conf;

  server {
    listen 80 default_server;

    include resty-server-http.conf;
  }

  include /etc/nginx/conf.d/*.conf;
}

stream {
 include /etc/nginx/streams/*.conf;
}
```

3\) edit this file: **/opt/elestio/nginx/docker-compose.yml** and add there a new line under volumes

**- /opt/elestio/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf**

It should look like this:

```
version: '2'
services:
  nginx:
    image: elestio/nginx-auto-ssl:latest
    container_name: elestio-nginx
    restart: always
    network_mode: "host"
    volumes:
      - /opt/elestio/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
      - /opt/elestio/nginx/ssl_data:/etc/resty-auto-ssl
      - /opt/elestio/nginx/conf.d:/etc/nginx/conf.d
      - /opt/elestio/nginx/streams:/etc/nginx/streams
      - /opt/elestio/nginx/logs:/var/log/nginx/
      - /root/.acme.sh/vm.elestio.app/fullchain.cer:/etc/nginx/certs/cert.pem
      - /root/.acme.sh/vm.elestio.app/vm.elestio.app.key:/etc/nginx/certs/key.pem
    env_file:
      - .env
```

4\) Restart nginx with this command:

```bash
cd /opt/elestio/nginx/;
docker-compose down;
docker-compose up -d;
```

Now nginx reverse proxy will use your custom global configuration

# Using Cloudflare

##### **Cloudflare DNS:**

If you wish to use Cloudflare for DNS ONLY, you can configure it just like any other DNS provider, and simply [follow the steps for adding a custom domain as usual.](https://docs.elest.io/books/security/page/custom-domain-and-automated-encryption-ssltls)

<p class="callout warning">WARNING: Your domain DNS entry **must have a GRAY cloud, not an ORANGE (proxied) cloud next to the entry.**</p>

<p class="callout danger">[![image.png](https://docs.elest.io/uploads/images/gallery/2023-07/scaled-1680-/image.png)**Using Cloudflare's proxy for your domain without additional configuration will cause all incoming connections to fail!**](https://docs.elest.io/uploads/images/gallery/2023-07/image.png)</p>

<p class="callout success">[![image.png](https://docs.elest.io/uploads/images/gallery/2023-07/scaled-1680-/gMYimage.png) This is the correct image shown for DNS-only entries.](https://docs.elest.io/uploads/images/gallery/2023-07/gMYimage.png)</p>

##### **Cloudflare Proxy**

Even though Elest.io automatically provides SSL and has a firewall, there can be advantages to using Cloudflare for Proxying traffic, notably DDoS attacks and automatic filtering of scripted attacks.

<p class="callout warning">Note: [Cloudflare only proxies traffic on certain ports.](https://developers.cloudflare.com/fundamentals/get-started/reference/network-ports/) If you want to use this hostname for SSH, FTP, or other services whose ports are not listed in the above link, you must configure Cloudflare to provide DNS only or use [Cloudflare's Spectrum offer.](https://www.cloudflare.com/en-gb/products/cloudflare-spectrum/)</p>

Because Elest.io already creates an SSL certificate for your website trusted by a root CA, the recommended configuration is to set Cloudflare to use Strict SSL verification when connecting to your server.

<p class="callout info">Before continuing, ensure you have already configured the domains [as per the instructions on the previous page.](https://docs.elest.io/books/security/page/custom-domain-and-automated-encryption-ssltls)</p>

##### Option 1: To set up strict SSL verification for your **whole domain**:

1. Navigate to the `SSL/TLS` section of your domain's dashboard.
2. Select the `"Full (strict)"` option.
3. Your changes will be saved automatically. You're done!

[![Screen Shot 2023-07-17 at 17.57.34.png](https://docs.elest.io/uploads/images/gallery/2023-07/scaled-1680-/screen-shot-2023-07-17-at-17-57-34.png)](https://docs.elest.io/uploads/images/gallery/2023-07/screen-shot-2023-07-17-at-17-57-34.png)


##### Option 2: To set up strict SSL verification for a **specific subdomain:**

1. In your domain's dashboard, navigate to `Rules > Configuration Rules` and click `Create Rule`
2. Name your rule, and configure the incoming request filters. [![Screen Shot 2023-07-17 at 18.07.16.png](https://docs.elest.io/uploads/images/gallery/2023-07/scaled-1680-/screen-shot-2023-07-17-at-18-07-16.png)](https://docs.elest.io/uploads/images/gallery/2023-07/screen-shot-2023-07-17-at-18-07-16.png)

3\. Configure the SSL to `Strict`

[![Screen Shot 2023-07-17 at 18.06.58.png](https://docs.elest.io/uploads/images/gallery/2023-07/scaled-1680-/screen-shot-2023-07-17-at-18-06-58.png)](https://docs.elest.io/uploads/images/gallery/2023-07/screen-shot-2023-07-17-at-18-06-58.png)

4\. Click `Save`

##### Option 3: Manual configuration (Advanced)

If you need a custom implementation, you can disable the creation of an SSL certificate with the following steps.

<p class="callout info">Create a CNAME record for your Cloudflare entry and point to the CNAME provided for that service in the Elestio dashboard.</p>

<p class="callout warning">These changes can be overwritten in the future if you modify the list of domains via the Elest.io dashboard.</p>

1\) Connect to the VM with SSH and type this:  
**nano /opt/elestio/nginx/.env**

there remove your domain from the first line and save with CTRL+X

then type this command:  
**cd /opt/elestio/nginx;**  
**docker-compose down;**  
**docker-compose up -d;**

After that, nginx won't try again to obtain an SSL certificate for your domain.

# Network Firewall

<p class="callout success">By default, we only open the ports necessary for the application you have deployed. </p>

#### How can I restrict access to my service by IP address?

From the Dashboard, select "***Security"***, then "***Show Settings"*** on the Firewall row

[![Screenshot 2022-09-29 163646.png](https://docs.elest.io/uploads/images/gallery/2022-09/screenshot-2022-09-29-163646.png)](https://docs.elest.io/uploads/images/gallery/2022-01/image-1643092204220.png)

From there you can modify, remove, or add new rules to open a port from your service to the internet (or just to a specific target IP).

<p class="callout info">All services come preconfigured with firewall rules that match the software you are deploying.</p>

> You have to keep port 80 open to any ipv4/ipv6 or else Letsencrypt won't be able to generate an SSL certificate.


##### Here is a compilation of the ports necessary for Elestio Automation:

<table id="bkmrk-mandatory-applicatio" style="border-collapse:collapse;width:99.2593%;height:236.296px;"><colgroup><col style="width:12.5739%;"></col><col style="width:12.5739%;"></col><col style="width:25.0233%;"></col><col style="width:25.0233%;"></col><col style="width:25.0233%;"></col></colgroup><tbody><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;">**Mandatory**</td><td class="align-center" style="height:29.537px;">**Application**</td><td class="align-center" style="height:29.537px;">**Protocol**</td><td class="align-center" style="height:29.537px;">**Port** </td><td class="align-center" style="height:29.537px;">**Usage**</td></tr><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;"> <span style="color:rgb(230,126,35);">✔️</span></td><td class="align-center" style="height:29.537px;">Input </td><td class="align-center" style="height:29.537px;">TCP</td><td class="align-center" style="height:29.537px;">22</td><td class="align-center" style="height:29.537px;">Automation SSH</td></tr><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;">❌</td><td class="align-center" style="height:29.537px;">Input </td><td class="align-center" style="height:29.537px;">UDP</td><td class="align-center" style="height:29.537px;">4242</td><td class="align-center" style="height:29.537px;">Nebula/ Global IP</td></tr><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;">❌</td><td class="align-center" style="height:29.537px;">Input </td><td class="align-center" style="height:29.537px;">TCP</td><td class="align-center" style="height:29.537px;">18345</td><td class="align-center" style="height:29.537px;">VS Code</td></tr><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;">❌</td><td class="align-center" style="height:29.537px;">Input </td><td class="align-center" style="height:29.537px;">TCP</td><td class="align-center" style="height:29.537px;">18374</td><td class="align-center" style="height:29.537px;">Open Terminal</td></tr><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;">❌</td><td class="align-center" style="height:29.537px;">Input </td><td class="align-center" style="height:29.537px;">TCP</td><td class="align-center" style="height:29.537px;">18346</td><td class="align-center" style="height:29.537px;">File Explorer</td></tr><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;">❌</td><td class="align-center" style="height:29.537px;">Input</td><td class="align-center" style="height:29.537px;">TCP</td><td class="align-center" style="height:29.537px;">18445</td><td class="align-center" style="height:29.537px;">Tail Logs</td></tr><tr style="height:29.537px;"><td class="align-center" style="height:29.537px;">❌</td><td class="align-center" style="height:29.537px;">Input </td><td class="align-center" style="height:29.537px;">TCP</td><td class="align-center" style="height:29.537px;">18344</td><td class="align-center" style="height:29.537px;">Terminal</td></tr></tbody></table>

❌ =&gt; Ports are necessary only if you are utilizing specific tools and activating global private IP functionality.

# IP rate limiter

From the Dashboard, click on *Security* then Rate Limiter &gt; *Show Options.* From here, you can easily modify and adjust your service's rate limiter configurations, by amount and per minute or second, per IP address.

<p class="callout info">By default, all services are preconfigured with a rate limiter of 150 requests per minute and per IP address.</p>

<p class="callout warning">Rate limiter is used only for web traffic.</p>

[![Screenshot 2022-09-29 163748.png](https://docs.elest.io/uploads/images/gallery/2022-09/screenshot-2022-09-29-163748.png)](https://docs.elest.io/uploads/images/gallery/2022-01/image-1643092781684.png)

# Output Cache

From the Dashboard, navigate to the *Security* tab and select *Show Options* under Output Cache.  
  
From here, you can modify your output cache configurations.  
  
All GET requests are cached for 3 seconds, which is useful in preventing Denial of Service (DOS) attacks.

<p class="callout info">All services come preconfigured with Output cache by default.</p>

<p class="callout warning">Output cache is used for web traffic only.</p>

[![Screenshot 2022-09-29 165938.png](https://docs.elest.io/uploads/images/gallery/2022-09/screenshot-2022-09-29-165938.png)](https://docs.elest.io/uploads/images/gallery/2022-01/image-1643092949076.png)

# Termination protection & grace period

You can enable or disable the **Termination protection** option from your Dashboard *Overview*, using the toggle on the right-hand side. This setting is disabled by default.

[![Screenshot 2022-09-29 170057.png](https://docs.elest.io/uploads/images/gallery/2022-09/screenshot-2022-09-29-170057.png)](https://docs.elest.io/uploads/images/gallery/2022-01/image-1643093091284.png)

<p class="callout warning">It's not possible to change software versions, delete, shut down, power off, reset or reboot your service when Termination protection is enabled. To make these changes, you must first disable Termination protection.</p>

<p class="callout info">Our grace period for storing backups after the deletion of service is 7 days, making it easier for you to restore your service in this window of time for any reason.</p>

[![Screenshot 2022-09-29 150044.png](https://docs.elest.io/uploads/images/gallery/2022-09/screenshot-2022-09-29-150044.png)](https://docs.elest.io/uploads/images/gallery/2022-01/image-1643093244612.png)

# Manage SSH Keys

From the Dashboard, navigate to the *Security* tab and select the *Show Options* button to Manage SSH Keys.  
From here, you can add or remove SSH keys allowed on the server.  
  
**Add an SSH key**  
Click on the *Add key*. Simply give your key a title and save!  
  
**Deleting an SSH key**  
Select the 'trash' icon to the right of the key you wish to delete. We'll always double-check with you before making a deletion, just to be sure!

[![Managed Service Dashboard (1).png](https://docs.elest.io/uploads/images/gallery/2022-09/managed-service-dashboard-1.png)](https://docs.elest.io/uploads/images/gallery/2022-01/image-1643093450138.png)

# How to connect to an Elestio service with SSH keys

## <span style="color:rgb(0,0,0);">Connecting to an Elestio service Using Existing SSH Keys from a Mac/Linux Machine</span>

### <span style="color:rgb(0,0,0);">Step 1: Check for Existing SSH Key Pair</span>

<span style="color:rgb(0,0,0);">First, verify if you have an existing SSH key pair by checking the <span class="code">.ssh</span> directory. Open a terminal and execute the following command:</span>

```
ls ~/.ssh
```

<span style="color:rgb(0,0,0);">The file with the <span class="code">.pub</span> extension is your public key.</span>

<span style="color:rgb(0,0,0);">If you don't have an existing SSH key pair, you can generate a new one using the following command:</span>

```
ssh-keygen -b 4096 -t rsa
```

### <span style="color:rgb(0,0,0);">Step 2: Copy your SSH Public Key to your Elestio service</span>

1. <span style="color:rgb(0,0,0);">Copy the Public Key to Clipboard:</span>  
    <span style="color:rgb(0,0,0);">Navigate to the <span class="code">.ssh</span> directory by typing</span>

```
cd .ssh
```

<span style="color:rgb(0,0,0);">Display the contents of your public key using <span class="code">cat</span>. For example, if your public key is <span class="code">id\_ed255518.pub</span>, you can view it with:</span>

```
cat ~/.ssh/id_ed255518.pub
```

<span style="color:rgb(0,0,0);">Copy the displayed public key and add it to your Elestio service.</span>

2. <span style="color:rgb(0,0,0);">Add the Public Key to Elestio:</span>
    
    
    - <span style="color:rgb(0,0,0);">Open your Elestio service and navigate to the 'Security' tab.</span>
    - <span style="color:rgb(0,0,0);">Go to **<span style="background-color:rgb(255,255,255);">*'<span style="color:rgb(230,126,35);">[Manage SSH Keys](https://docs.elest.io/books/security/page/manage-ssh-keys "Manage SSH Keys")'</span>*</span>** and click on the 'Add key' button.</span>
    - <span style="color:rgb(0,0,0);">Paste your public key into the provided field.</span>

### <span style="color:rgb(0,0,0);">Step 3: Confirm and Test Connection</span>

<span style="color:rgb(0,0,0);">To test the SSH connection to your VM, use the following command from your local machine:</span>

```
ssh root@IPV4_TARGET_VM
```

<span style="color:rgb(0,0,0);">Replace "IPV4\_TARGET\_VM" with the actual IPv4 address of your target VM, which you can find in the 'Overview' tab of your service.</span>  
  
<span style="color:rgb(0,0,0);"> For example:</span>

```
ssh root@128.144.84.22
```

<span style="color:rgb(0,0,0);">If the connection is successful, you'll be logged into your VM 🚀</span>

---

## <span style="color:rgb(0,0,0);">Connecting to an Elestio service Using Existing SSH Keys from a Windows Machine with WSL (Windows Subsystem for Linux)</span>

### <span style="color:rgb(0,0,0);">Step 1: Set up WSL (Windows Subsystem for Linux)</span>

<span style="color:rgb(0,0,0);">Before proceeding, you need to ensure that WSL is installed and configured on your Windows machine. Here's how you can set up WSL:</span>

1. <span style="color:rgb(0,0,0);">Enable WSL: Open PowerShell as Administrator and run the following command:</span>
    
    ```
    wsl --install
    ```
    
    <span style="color:rgb(0,0,0);">This command will automatically enable the necessary features and install the latest version of WSL on your system.</span>
2. <span style="color:rgb(0,0,0);">Install a Linux Distribution: After WSL is installed, visit the Microsoft Store and search for your preferred Linux distribution (e.g., Ubuntu). Click "Install" to download and install it.</span>
3. <span style="color:rgb(0,0,0);">Initialize WSL: Once the distribution is installed, launch it from the Start menu. This will initialize the distribution and prompt you to create a user account and set up a password.</span>
4. <span style="color:rgb(0,0,0);">Update and Upgrade: After the setup is complete, it's a good idea to update and upgrade the packages within your Linux distribution to ensure you have the latest versions. You can do this by running the following commands:</span>
    
    ```
    sudo apt update sudo apt upgrade
    ```
    
    <span style="color:rgb(0,0,0);">Follow the same tutorial to connect to an Elestio service using existing SSH keys from a Mac/Linux machine.</span>

# SMTP service

All deployed services include a basic preconfigured SMTP service, useful for sending alerts and notifications from your service.

This is free, but comes with a few limitations:

- You can only send transactional emails. Marketing emails are not permitted.   
    <p class="callout danger">*Any violation of this will lead to a suspension or termination of your service.*</p>
- You can send up to 300 transactional emails per hour. That's up to 7200 emails per day!
- All emails must be sent from **\[domain\]@vm.elestio.app** where **\[domain\]** is the URL of your service.  
    <p class="callout warning">*Attempts at sending from any other email address will be rejected.*</p>
- The SMTP service is only available from the global private network IP of your VM.

Of course in several cases you will want to change the smtp configuration in the web UI of your software to use another smtp service. It's useful if you want to be able to configure another sender address or to overcome any limitations stated above.

Check out our list of recommended SMTP providers:

- [AWS SES](https://aws.amazon.com/ses/)
- [SendInBlue](https://www.sendinblue.com/)
- [Mailgun](https://www.mailgun.com/)
- [Sendgrid](https://sendgrid.com/)

# Multi-factor authentication

By default, Elestio uses Email-based MFA, each time you log in to Elestio we will send you an email with a one-time code to enter into our UI to be able to connect. This protection is in place to enforce security and avoid account hacking.

We also have TOTP-based MFA, this is more secure because it's based on an app installed on your phone to generate TOTP codes instead of us sending them by email. So even if your mailbox is compromised your Elestio account will still be safe.

We recommend all users use TOTP Generator, you can activate it in a few clicks from our dashboard &gt; user profile &gt; Security tab.

[![Screenshot 2022-11-10 181459.png](https://docs.elest.io/uploads/images/gallery/2022-11/scaled-1680-/screenshot-2022-11-10-181459.png)](https://docs.elest.io/uploads/images/gallery/2022-11/screenshot-2022-11-10-181459.png)

[![Managed Service Dashboard (16).png](https://docs.elest.io/uploads/images/gallery/2022-11/scaled-1680-/managed-service-dashboard-16.png)](https://docs.elest.io/uploads/images/gallery/2022-11/managed-service-dashboard-16.png)

**The process to activate TOTP MFA on your account**

1. Open the account security tab here: **[https://dash.elest.io/account/security](https://dash.elest.io/account/security)**
2. Click on Configure button in Manage Two-Factor Authentication.
3. Select the **Authenticator App** tab.
4. Download an authenticator app: **[Authy](https://authy.com/download/)** (recommended) or **[Google Authenticator](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2)** or **[Microsoft Authenticator](https://www.microsoft.com/en-us/security/mobile-authenticator-app)**
5. Open your authenticator app then scan the QR code on the screen
6. Generate a code with your app and enter it on the Elestio screen
7. Click on Validate

Done, Strong MFA is now enabled on your account, and will be required to login into your Elestio account

<p class="callout info">You should keep the text version somewhere safe (in orange in the screenshot), this will allow you to recover in case you lose your phone or authenticator app.</p>

<p class="callout warning">If you have lost both your authenticator app and text secret, you can contact our support team via [<span style="color:rgb(186,55,42);">***email*** </span>](mailto:support@elest.io)with proof of identity to get MFA removed from your account.</p>

**The process to Activate Email Based MFA on your account**

1. Open the account security tab here: **[https://dash.elest.io/account/security](https://dash.elest.io/account/security)**
2. Click on Configure button in Manage Two-Factor Authentication.
3. Select the **Email Based** tab.
4. Click on Enable button to activate it.

[![Screenshot 2022-11-10 183750.png](https://docs.elest.io/uploads/images/gallery/2022-11/scaled-1680-/screenshot-2022-11-10-183750.png)](https://docs.elest.io/uploads/images/gallery/2022-11/screenshot-2022-11-10-183750.png)

**The process to Deactivate MFA on your account**

1. Open the account security tab here: **[https://dash.elest.io/account/security](https://dash.elest.io/account/security)**
2. Click on Configure button in Manage Two-Factor Authentication.
3. Select the **Disabled** tab.
4. To confirm the action, type disable in the confirmation input field on the confirmation modal.
5. Click on Disable button to disable it.

[![Screenshot 2022-11-10 184733.png](https://docs.elest.io/uploads/images/gallery/2022-11/scaled-1680-/screenshot-2022-11-10-184733.png)](https://docs.elest.io/uploads/images/gallery/2022-11/screenshot-2022-11-10-184733.png)

# How to Enable or Disable IPv6 on a Linux Virtual Machine

<div id="bkmrk-ipv6-is-the-latest-v">IPv6 is the latest version of the Internet Protocol, designed to address the limitations of IPv4. In some scenarios, such as managing Docker Hub rate limits, disabling IPv6 may be necessary to ensure smooth operation. This guide provides step-by-step instructions for enabling or disabling IPv6 on a Linux VM.</div><div id="bkmrk-"></div><div id="bkmrk--1"></div><div id="bkmrk--2"></div><div id="bkmrk--3"></div>> <div>If you are encountering issues with the Docker Hub rate limit, it is recommended to disable IPv6 on your VM by following the steps outlined in the "Disabling IPv6" section below.</div>

<div id="bkmrk--4">  
</div><div id="bkmrk-first%2C-open-the-term">First, open the terminal by selecting the "Open Terminal" option located at the top-right corner of the service details overview. Then, proceed with the steps for either enabling or disabling IPv6, depending on your requirements.</div>##### **Enabling IPv6**

<div id="bkmrk-if-ipv6-is-currently">If IPv6 is currently disabled on your VM and you want to enable it, follow these steps:</div><div id="bkmrk--5"></div>**1. Temporarily Enable IPv6:** To enable IPv6 without rebooting:

```bash
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=0
```

This change will revert after a system reboot.

**2. Permanently Enable IPv6:** To enable IPv6 persistently:

- Edit the `sysctl.conf` file:

```
sudo nano /etc/sysctl.conf
```

- Locate and comment out the following lines (if present):

```
# net.ipv6.conf.all.disable_ipv6 = 1
# net.ipv6.conf.default.disable_ipv6 = 1
```

- Apply the changes:

```
sudo sysctl -p
```

IPv6 will now remain enabled even after a reboot.

---


##### **Disabling IPv6**

If IPv6 is causing issues, such as with Docker Hub rate limits, follow these steps to disable it.

**1. Temporarily Disable IPv6:**  To disable IPv6 without rebooting:

```
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
```

This change is not permanent and will be reset after a reboot.

**2. Permanently Disable IPv6:** To disable IPv6 persistently:

- Edit the `sysctl.conf` file:

```
sudo nano /etc/sysctl.conf
```

- Add the following lines to the file:

```
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
```

- Apply the changes:

```
sudo sysctl -p
```

IPv6 will now remain disabled even after a reboot.

# How to configure NGINX to Listen on IPv6

IPv6 is quickly becoming standard. If your VM already supports it, you just need to tell NGINX to listen on an IPv6 socket.

*(If IPv6 is disabled on the VM itself, start with the “Enable IPv6 on your VM” article and come back here.)*

#### 1. Open the dashboard

<div id="bkmrk-go-to-your-project-%E2%86%92">1. Go to your project → **Services** → **Security** tab.
2. Click **NGINX Configuration › Show config**.

</div>[![Screenshot 2025-05-14 at 15.16.43.png](https://docs.elest.io/uploads/images/gallery/2025-05/scaled-1680-/screenshot-2025-05-14-at-15-16-43.png)](https://docs.elest.io/uploads/images/gallery/2025-05/screenshot-2025-05-14-at-15-16-43.png)

#### 2 . Edit the server block for your domain

Choose your domain and find edit the NGINX config then find

`<span class="hljs-attribute">listen 443 ssl http2;</span>`

<div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary" id="bkmrk--1"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none rounded-t-[5px]"><div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary">  
</div></div></div>Add the IPv6 line directly beneath:

`listen 443 ssl http2;listen [::]:443 ssl http2; `

*(Keep the original IPv4 line—now NGINX will listen on both stacks.)*

*[![Screenshot 2025-05-14 at 15.35.26.png](https://docs.elest.io/uploads/images/gallery/2025-05/scaled-1680-/screenshot-2025-05-14-at-15-35-26.png)](https://docs.elest.io/uploads/images/gallery/2025-05/screenshot-2025-05-14-at-15-35-26.png)*

Click **Apply &amp; Restart**. NGINX reloads and your server is now ready to serve HTTPS traffic over IPv6.

<article class="text-token-text-primary w-full" dir="auto" id="bkmrk--3"><div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col grow"><div class="min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&]:mt-5" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]"><div class="markdown prose dark:prose-invert w-full break-words dark">  
</div></div></div></div><div class="flex justify-start">  
</div><div class="mt-3 w-full empty:hidden"><div class="text-center">  
</div></div></div></div></div></div></article>

# How to secure your application with Cloudflare Tunnel

<article class="text-token-text-primary w-full" dir="auto" id="bkmrk--3">## What is Cloudflare Tunnel?

Cloudflare Tunnel is a secure solution that connects your web applications to Cloudflare's global network without exposing your server's IP address or opening inbound ports. It creates an encrypted tunnel between your origin server and Cloudflare's edge, providing enhanced security and performance for your applications.

## Why Use Cloudflare Tunnel?

### Key Benefits:

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center">- No exposed IP addresses: Your server's IP remains completely hidden
- No open inbound ports: Eliminates common attack vectors
- Built-in DDoS protection: Leverages Cloudflare's network
- End-to-end encryption: Secure communication throughout
- Easy setup: No complex firewall configurations needed
- Global performance: Benefits from Cloudflare's CDN

</div></div></div></div></div></div>## Getting Started with Cloudflare Tunnel

### Prerequisites

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center">- A Cloudflare account (free tier is sufficient)
- A domain configured in Cloudflare
- Access to your server or application host
- Basic command-line knowledge

</div></div></div></div></div></div>## Step-by-Step Installation Guide

### Step 1: Access Zero Trust Dashboard

Navigate to your Cloudflare dashboard and click on **Zero Trust** in the sidebar. This is where all tunnel management happens.

When installing Cloudflare on your Elestio service, make sure to select **Debian** as the operating system.  
Next, open your **Elestio Terminal**. Once inside, install Cloudflare and set up the service to run your tunnel by copying and pasting the commands provided by Cloudflare.

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center"><figure class="kg-card kg-image-card">![](https://blog.elest.io/content/images/2025/10/image--12--1.png)</figure><figure class="kg-card kg-image-card">![](https://blog.elest.io/content/images/2025/10/image--13-.png)</figure></div></div></div></div></div></div>### Step 2: Navigate to Tunnels

Under the **Networks** section, click on **Tunnels**. This is your central hub for creating and managing all your tunnels.

Click **"Create a tunnel"** to begin the setup process. You'll be presented with two options:

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center">- **Cloudflared (Recommended)**: The standard option for most use cases
- **WARP Connector**: For advanced networking scenarios

</div></div></div></div></div></div>Select **Cloudflared** for this guide.

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center"><figure class="kg-card kg-image-card">![](https://blog.elest.io/content/images/2025/10/image--2-.png)</figure></div></div></div></div></div></div>Choose a descriptive name for your tunnel. This helps you identify it later, especially if you manage multiple tunnels.

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center"><figure class="kg-card kg-image-card">![](https://blog.elest.io/content/images/2025/10/image--3-.png)</figure></div></div></div></div></div></div>Click **"Save tunnel"** to proceed.

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center"><figure class="kg-card kg-image-card">![](https://blog.elest.io/content/images/2025/10/image--4-.png)</figure></div></div></div></div></div></div>### Step 3: Configure Your Application Route

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center"><figure class="kg-card kg-image-card">![](https://blog.elest.io/content/images/2025/10/image--16-.png)</figure></div></div></div></div></div></div>Hostname Configuration:

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center">- **Subdomain**: Choose your desired subdomain (e.g., "app", "api", "blog")
- **Domain**: Select from your Cloudflare-managed domains
- **Path**: Optional path prefix for routing

</div></div></div></div></div></div>#### Service Configuration:

You can easily find the correct port by clicking **Update Config** in the **Overview** tab of your service, then checking the **Ports** section to see which port your application is bound to.

Click **"Save"** to finalize your configuration. Your tunnel is now active and routing traffic!

Cloudflare Tunnel revolutionizes how we expose applications to the internet. By eliminating the need for public IP addresses and open ports, it significantly reduces attack surface while providing enterprise-grade performance and security.

Combining Elestio's managed infrastructure with Cloudflare Tunnel gives you professional-grade deployment with minimal complexity - perfect for securing your applications, APIs, and services behind Cloudflare's global network.

<div class="text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group/turn-messages focus-visible:outline-hidden" tabindex="-1"><div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn"><div class="relative flex-col gap-1 md:gap-3"><div class="mt-3 w-full empty:hidden"><div class="text-center">  
</div></div></div></div></div></div></article>

# Custom domain and automated encryption (SSL/TLS)

##### Prerequisites

<span style="background-color:rgb(255,255,255);color:rgb(224,62,45);">If the firewall is enabled on your service, ensure that **port 80 is open**. This is required for SSL certificate creation and renewal.</span>

---

##### Accessing the Configuration

1. Go to the **Overview** tab of your service dashboard.
2. Locate the **Custom Domain Names** section inside the **Domain Management** tab.
3. Click **Manage Domains**.

[![image.png](https://docs.elest.io/uploads/images/gallery/2026-04/scaled-1680-/BQ9image.png)](https://docs.elest.io/uploads/images/gallery/2026-04/BQ9image.png)

In this section, you will have two ways to configure custom domains.

---

##### **Method 1: Manual DNS Setup**

[![image.png](https://docs.elest.io/uploads/images/gallery/2026-04/scaled-1680-/0uximage.png)](https://docs.elest.io/uploads/images/gallery/2026-04/0uximage.png)

1. In this step, enter your domain and press **Enter** to add it to the list of authorized domains.
2. Configure DNS records in your domain registrar panel.

**Required DNS Records**

- **A record**:  
    `@` → `<service IPv4>`  
    (Points the root domain to your service IP)
- **CNAME record**:  
    `www` → `<service CNAME>`  
    *(Recommended remains stable even if your IP changes, e.g., after migration.)*

3. Verify DNS propagation using a tool like: [https://dnschecker.org/](https://dnschecker.org/)

Once propagation is complete, the SSL certificate will be **automatically generated and renewed**, and HTTPS will start working.

---

##### **Method 2: One-Click DNS Setup via Cloudflare (Domain Connect)**

A **One-click DNS Setup** section is available if the domain name server or registrar is Cloudflare, allowing automatic DNS configuration via the Domain Connect protocol.

[![image.png](https://docs.elest.io/uploads/images/gallery/2026-04/scaled-1680-/q54image.png)](https://docs.elest.io/uploads/images/gallery/2026-04/q54image.png)

##### Steps

1. Enter your domain (e.g. `example.com`).
2. Click **Connect Domain**.
3. This action will redirect you to the Cloudflare dashboard for accepting the DNS record configuration.

---

##### **Environment Variable Update**

Some applications require updating an environment variable to reflect the configured domain.

[![image.png](https://docs.elest.io/uploads/images/gallery/2026-04/scaled-1680-/opkimage.png)](https://docs.elest.io/uploads/images/gallery/2026-04/opkimage.png)

To update:

1. Go to the **Overview** page of your service.
2. Click the **Update Config** tab in the software row.
3. Open the **Env** tab.
4. Update the domain-related environment variable.

---

##### **Cloudflare Reverse Proxy Users**

If you are using method 1 and want Cloudflare with the proxy enabled (orange cloud icon), refer to the detailed guide:

[https://docs.elest.io/books/security/page/using-cloudflare](https://docs.elest.io/books/security/page/using-cloudflare)

---

##### **Troubleshooting: SSL Not Generated**

**View Nginx Logs**

You can inspect logs using a terminal command:

```
cd /opt/elestio/nginx;
docker-compose logs -f;
```

Press `Ctrl + C` to stop live log output.

---

##### **Reset SSL Data Folder**

In some cases, the SSL data directory **/opt/elestio/nginx/ssl\_data** may become corrupted:

To fix:

1. Connect to your service via terminal.
2. Run the below command.

```
cd /opt/elestio/nginx/;
docker-compose down;
mv ./ssl_data/ ./ssl_data_old/;
mkdir ./ssl_data/;
chmod 777 ./ssl_data/;
docker-compose up -d
```

Once executed, just open your custom website URL again, and your certificate should be generated and your site served over SSL/TLS.

# PTR Record Configuration

##### Accessing the Configuration

1. Go to the **Overview** tab of your service dashboard.
2. Locate the **Manage PTR Record** section.
3. Click **Manage PTR Record**

[![image.png](https://docs.elest.io/uploads/images/gallery/2026-04/scaled-1680-/o8Qimage.png)](https://docs.elest.io/uploads/images/gallery/2026-04/o8Qimage.png)

### Steps

1. Enter your domain (pre-filled if an existing PTR or CNAME is available).
2. Create the following DNS records:
    
    
    - **A record** → Service IPv4
    - **AAAA record** → Service IPv6
3. Verify propagation using the ***<span style="color:rgb(230,126,35);">[DNSChecker](https://dnschecker.org/)</span>***.
4. Click **Update** to apply changes.

### Provider-Specific Notes

- **DigitalOcean**
    
    
    - The system will reboot after applying changes.
    - PTR updates may take a few hours due to DNS caching.
- **Scaleway**
    
    
    - For SMTP servers, IPv6 may need to be disabled on the VM.