---
title: 'Tutorial: Secure Access to code-server or OpenVSCode Server Without Exposing It to the Internet'
canonical: https://openvpn.net/as-docs/v3/tutorials/tutorial--code-server-private-access/
product: Access Server Docs
description: Learn how to access code-server or OpenVSCode Server remotely without exposing it to the public internet — bind the service to your VPN interface, route access through Access Server, and lock it down to VPN-only traffic with firewall rules.
---

# Tutorial: Secure Access to code-server or OpenVSCode Server Without Exposing It to the Internet

## Overview

Self-hosted development environments such as **code-server** and **OpenVSCode Server** let you run Visual Studio Code on a remote Linux server and access it from any device via a web browser.

Because these applications provide direct access to your development environment, they shouldn't be exposed directly to the public internet. Traditional deployments often require reverse proxies, public DNS records, firewall rules, and additional authentication layers to secure access.

With OpenVPN Access Server, you can keep your development environment private by making it accessible only through an authenticated VPN connection. Access Server also lets you control who can access the server using user- and group-based access rules. For example, you can allow only members of your **Developers** group to reach the code-server host while preventing access from other VPN users.

In this tutorial, you'll:

- Deploy code-server on a Linux server.
- Configure Caddy as an HTTPS reverse proxy.
- Restrict access with an Access Server group access rule.
- Connect securely with OpenVPN Connect.
- Verify that code-server is available only through the VPN.

## Prerequisites

- Access Server 3.1.0 or newer to use [domain routing](https://openvpn.net/as-docs/v3/tutorials/tutorial--domain-routing-in-access-server.md).
- An Access Server [user group](https://openvpn.net/as-docs/v3/tutorials/tutorial--adding-groups.md) called **Developers**.
- A Linux server where code-server will be installed.

  > **Tip**
  >
  > Deploy this server with at least 2 vCPUs and 1GB of RAM.
- The Linux server must be on the same private network as Access Server or be reachable via subnet routing.
- Administrative access to the Linux server.
- OpenVPN Connect on the developer's device.

## Step 1: Deploy a Linux server for code-server

Deploy a new Linux server in the same environment as your Access Server. This tutorial uses Ubuntu 24.04 LTS.

> **Important**
>
> Deploy code-server in the same cloud provider or network as your Access Server so both systems can communicate over private IP addresses.
>
> If you deploy them in separate networks or virtual private clouds, configure VPC peering or another private routing method that allows Access Server to route traffic to the code-server host. Refer to your cloud provider's documentation for the required networking steps.

1. Create a new Linux server instance in your environment. This can be:
   - A cloud virtual machine, such as an Amazon EC2 instance.
   - A virtual machine in your virtualization platform.
   - A bare-metal server.
2. Install Ubuntu 24.04 LTS or another supported Linux distribution.
3. Place the server on the same private network as Access Server to configure routing between the networks.
4. Record the server's private IP address. This tutorial uses `192.0.2.15`.
5. Confirm that you can connect to the server through SSH or its console.

## Step 2: Connect to the server and install code-server

Connect to the Linux server, install code-server, and configure it to accept connections only from the local Caddy reverse proxy.

1. Open a terminal or SSH client.
2. Connect to the server using your SSH user. Example command:

   ```
   ssh -i /path/key-pair-name.pem <ssh-user>@<instance-ipv4-address>
   ```

   Replace `/path/key-pair-name.pem` with your private SSH key.

   Replace `<ssh-user>` with your SSH user.

   Replace `<instance-ipv4-address>` with your instance's public IP address.

   > **Tip**
   >
   > You can refer to [Tutorial: Connect to Access Server via SSH using PuTTY](https://openvpn.net/as-docs/v3/tutorials/tutorial--connect-with-putty.md) for steps to connect with the PuTTY SSH client from a Windows computer. If you have a different configuration, please follow your cloud provider’s instructions on connecting to your instance.
3. Install code-server:

   ```
   curl -fsSL https://code-server.dev/install.sh | sh
   ```
4. Enable and start the code-server service so it starts automatically after system reboots:

   ```
   systemctl enable --now code-server@$USER
   ```
5. Open the code-server configuration file:

   ```
   ~/.config/code-server/config.yaml
   ```
6. Replace its contents with:

   ```
   bind-addr: 127.0.0.1:8080
   auth: none
   cert: false
   ```

   This configuration:
   - Binds code-server to the local loopback interface.
   - Prevents direct network access to port `8080`.
   - Disables code-server password authentication.
   - Leaves HTTPS termination to Caddy.

   > **Note**
   >
   > Access Server authenticates the VPN user before permitting access to the code-server host.
7. Save and close the file.
8. Restart code-server:

   ```
   sudo systemctl restart code-server@$USER
   ```
9. Confirm that the service is running:

   ```
   systemctl status code-server@$USER
   ```

> **Important**
>
> Don’t expose the code-server service directly to the internet. This tutorial assumes that users can reach it only through an authenticated VPN connection and the Caddy reverse proxy configured in the next step.

## Step 3: Install and configure Caddy for code-server

Caddy provides the HTTPS endpoint and forwards authorized connections to code-server on `127.0.0.1:8080`.

Configure Caddy to listen only on the server's private IP address.

1. Install Caddy. Refer to the [Caddy installation documentation](https://caddyserver.com/docs/install) for your Linux distribution.
2. Identify the server's private network interface:

   ```
   ip -4 add
   ```
3. Record the interface name associated with the private IP address. For example:

   ```
   eth1
   ```
4. Store the private IP address in a shell variable:

   ```
   PRIVATE_IP=$(ip -4 addr show eth1 | grep -o 'inet [0-9.]*' | cut -d' ' -f2)
   ```

   Replace `eth1` with the private network interface for your server.
5. Display the value:

   ```
   echo "$PRIVATE_IP"
   ```

   - Example output:

     ```
     192.0.2.15
     ```
6. Create the Caddy configuration:

   ```
   sudo tee /etc/caddy/Caddyfile > /dev/null <<EOF
      ${PRIVATE_IP} {
       reverse_proxy localhost:8080
   }
   EOF
   ```
7. Restart Caddy:

   ```
   sudo systemctl restart caddy
   ```
8. Confirm that Caddy is running:

   ```
   systemctl status caddy
   ```

> **Note**
>
> Caddy’s internal certificate authority issues the certificate used for this private HTTPS endpoint. A developer device may need to trust the Caddy root certificate before the browser recognizes the connection as trusted.

### Optional: Configure a domain name

You can use a domain name such as `code-server.example.com` instead of connecting by private IP address. This also lets you configure [domain routing](https://openvpn.net/access-server/features/domain-routing/) in Access Server.

Ensure the domain name resolves to the code-server host's private IP address for connected VPN clients.

1. Edit the Caddy configuration:

   ```
   sudo tee /etc/caddy/Caddyfile > /dev/null <<'EOF'
      code-server.example.com {
         tls internal
         reverse_proxy localhost:8080
      }
   EOF
   ```

   Replace `code-server.example.com` with your internal hostname.
2. Restart Caddy:

   ```
   sudo systemctl restart caddy
   ```
3. Confirm that the service is running:

   ```
   systemctl status caddy
   ```

## Step 4: Configure Access Server to secure code-server

Configure an access rule that permits only members of the **Developers** group to reach the code-server HTTPS endpoint.

> **Important**
>
> Access Server must have private network connectivity to the code-server host. When the systems are in separate networks or VPCs, configure private routing or VPC peering before creating the access rule.

1. Sign in to the Admin Web UI.
2. Select **Groups**.
3. Select the **Developers** group.
4. Select the **Access Rules** tab.
5. Select **New Access Rule**.
6. Configure the rule:
   - **Address:** `192.0.2.15/32`
   - **Protocol:** TCP
   - **Port:** `443`
7. Select **Save** and **Restart**.

> **Tip**
>
> Creating the rule for the **Developers** group limits access to users in that group. Other VPN users can't reach the code-server host unless another access rule grants them access.

### Optional: Configure domain routing

If you configured an internal hostname for code-server, create a domain access rule instead of, or in addition to, the IP address rule.

1. Sign in to the Admin Web UI.
2. Select **Groups**.
3. Select the **Developers** group.
4. Select the **Access Rules** tab.
5. Select **New Access Rule**.
6. Configure the domain rule:
   - **Domain name:** `code-server.example.com`
7. Select **Save** and **Restart**.

## Step 5: Verify access through the VPN

Confirm that an authorized developer can reach code-server through the VPN and that the service is unavailable without the VPN connection.

1. Ensure the test user belongs to the **Developers** group.
2. Open OpenVPN Connect on the developer's device.
3. Connect to Access Server.
4. Open a web browser.
5. Navigate to the private IP address:

   ```
   https://192.0.2.15
   ```

   Or, when using a domain name:

   ```
   https://code-server.example.com
   ```
6. Confirm that the code-server interface displays.
7. Disconnect from the VPN.
8. Refresh the page or try to open the URL again.

**Expected result:** The developer can reach code-server while connected to Access Server. After disconnecting from the VPN, the connection fails because the service isn’t exposed to the public internet.

## Result

You now have a self-hosted development environment that:

- Runs privately on your network.
- Uses Caddy to provide HTTPS.
- Is reachable only through an authenticated VPN connection.
- Limits access to members of the **Developers** group.
- Doesn't require exposing the code-server service itself to the internet.

---

Prev: [Tutorial: Secure Database Access Without Exposing Your Database to the Internet](https://openvpn.net/as-docs/v3/tutorials/tutorial--protect-database-access-server.md)
Next: [Performance & Scalability](https://openvpn.net/as-docs/v3/tutorials/performance---scalability.md)
Index: https://openvpn.net/as-docs/llms.txt
