code-server-ipad I believe that browser based development has finally become just as good as running an IDE locally on your device. You can have all the benefits of local development: competent hardware, familiar IDE with keyboard shortcuts, and not having to worry about platform compatibility. All of this, in addition to the portability benefits of it being fully contained in the browser. This means all your installed extensions and settings follow you to every device — including an iPad!

There are several tutorials on how to set up code-server, but code-server by itself is not safe to expose over the internet. In this guide, we’ll set up code-server behind a secure VPN and handle all the requirements for HTTPs with a few configurations and commands.


To accomplish this, we’ll be using the following technologies:

  • Code Server — one of the most popular code editors is now available in a browser. While the official release (at the time of this writing) is still in private preview, there are 3rd party implementations that are available.
  • Tailscale — a zero config VPN that will greatly simplify how we access code-server in a secure and encrypted way. I’ve already mentioned in a previous post some of the other reasons why I think it’s great.
  • Caddy — A web server that provides automatic HTTPS. This is important as certain features on code-server are restricted unless they’re over TLS.
  • Docker Compose — While you can install all of the above onto the host itself, I like to containerize my installations as much as possible. Docker Compose will help keep our configurations to a single file and keep maintenance nice and tidy.

You’ll also need:

  • A host (on GCP, AWS, DigitalOcean, etc.,) with at least 2 cores and 1GB memory — the recommended reqs to run code-server
  • A free account on Tailscale
  • Tailscale installed on any device you want to be able to access your code-server from


For this setup, I’ll be walking through the steps to set this up on a host running Ubuntu 22.04 (Jammy). If you’re using something else, see the notes below. Most of the steps should still be applicable. We’ll be installing Tailscale and docker/docker-compose on the host itself. Everything else will be run as a docker container.

Install docker and docker-compose.

curl -fsSL | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update -y && apt-get install -y docker-ce docker-compose

Install Tailscale using the sources for your OS. See here if you’re using something other than Jammy.

curl -fsSL | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update -y && apt-get install -y tailscale

Bring up tailscale. Running this for the first time will provide you with a link that will allow you to authenticate through a browser

sudo tailscale up

Once authenticated, this will add your host to your Tailscale network and you’ll need to Enable HTTPS under the DNS page. When complete, you’ll be provided a domain alias in the form of <hostname>.<domain_alias> that we’ll need to add to our configurations below.

Create the data volumes for code-server and caddy:

mkdir ~/code-server
docker volume create --name=caddy_data

And finally, create the following configuration files:

~/Caddyfile {
    redir /code /code/

    route /code/* {
        uri strip_prefix /code
        reverse_proxy code-server:8443


version: "2.1"


    container_name: code-server
      - PUID=1000
      - PGID=1000
      - TZ=America/Los_Angeles
      - DEFAULT_WORKSPACE=/config/workspace 
      - ~/code-server/config:/config
      - /var/run/docker.sock:/var/run/docker.sock # Allows ability to fetch tailscale certs
      - code-net
      - # reverse proxy code-server
    restart: unless-stopped
    image: caddy:latest # this is NOT recommended for a production site. Pin to a stable version
    container_name: caddy
    restart: unless-stopped
      - ~/Caddyfile:/etc/caddy/Caddyfile
      - /var/run/tailscale:/var/run/tailscale
      - caddy_data:/data
      - caddy_config:/config
      - code-net
      - 80:80 # caddy http
      - 443:443 # caddy https
    external: true

Bring up the containers:

docker-compose up -d

And that’s it! From here you should be able to access your code-server environment via https://<tailscale_host>.<tailscale_subdomain>