Setup Your Own Private Railway: Dokploy + Tailscale + Valid SSL on Proxmox LXC

18 October 2026
Homelab , DevOps , Tailscale , Proxmox

Every engineer loves the simplicity of Railway: push code, check a web dashboard, spin up a database, and watch your app go live with automatic domains and SSL. But paying commercial cloud PaaS prices for every staging branch, internal dashboard, or side project quickly adds up.

With modern open-source tooling, you can build your own private Platform as a Service (PaaS) on your own hardware. Even better: you can access it securely from anywhere in the world, with trusted HTTPS certificates, without opening a single port on your router.

Here is how to set up Dokploy inside an unprivileged Proxmox LXC, connect it securely via Tailscale, and get trusted Let’s Encrypt SSL certificates using the Cloudflare DNS-01 challenge.


Real-World Use Cases For This Setup

This architecture is versatile and solves two major engineering use cases:

  1. Zero-Trust Staging for Engineering Teams
    Small development teams often spend hundreds of dollars each month on commercial cloud staging environments. With this setup, you only need a single computer, a spare mini PC, or even multiple machines clustered together kept running at the office. Team members join the company Tailnet, deploy pull requests or staging branches onto Dokploy, and test them under realistic conditions. Because everything stays inside Tailscale, your staging applications, internal APIs, and pre-release features are never exposed to the public internet. No unauthorized visitors, no search engine indexing, and zero risk of accidental data leaks.

  2. Homelab, Self-Hosting, and Private AI Assistants
    For personal use, this turns your homelab or home server into a private cloud. You can host your everyday services (such as Nextcloud, Vaultwarden, Home Assistant, or personal web apps) with a clean web interface, automated backups, and painless updates on your own hardware. It is also the ideal environment for deploying 24/7 private AI assistants using tools like OpenClaw or Hermes. Instead of paying hefty cloud compute bills for continuous background workers, headless Chromium browsers, and vector memory, you keep your API keys, private documents, and conversation history 100% on your own hardware. Through Tailscale and Traefik, you get a clean HTTPS domain (such as https://assistant.yourdomain.com) that you can chat with or call via webhook from your laptop or phone anywhere, without ever exposing anything to the public internet.


The Architecture: Why These Tools?

Before jumping into terminal commands, here is what each component does and why it was chosen:

  • Proxmox VE & LXC Containers: Installing Proxmox VE gives you vastly more flexibility than installing a standard Linux distribution directly on your server hardware. With Proxmox, you can easily spin up, clone, snapshot, and delete multiple isolated virtual machines (VMs) or lightweight Linux Containers (LXC), while assigning precise resource limits (CPU cores, RAM limits, and disk quotas) to each. This makes experimentation safe and painless: you can test new stacks without risking the stability of your host system. For Dokploy, we deploy inside an unprivileged LXC container because it shares the host Linux kernel, delivering near-native bare-metal speed, instant boot times, and minimal RAM and CPU overhead.
  • Dokploy: An open-source, self-hosted PaaS alternative to Railway, Heroku, or Coolify. It provides an intuitive web UI to manage Docker containers, databases (Postgres, MySQL, Redis, Mongo), Git deployments, and routing.
  • Tailscale: A zero-config mesh VPN built on WireGuard. Instead of opening router ports (like 80 or 443) or dealing with dynamic DNS and exposing your home or office IP to internet scanners, Tailscale creates a private, encrypted network (your “Tailnet”). Only authenticated devices can access your services.
  • Traefik (Dokploy’s Built-in Reverse Proxy): Traefik sits in front of all your Dokploy applications. It listens for incoming web requests, routes traffic to the correct container, and handles SSL certificate provisioning automatically.
  • Cloudflare DNS + DNS-01 Challenge:
    • The problem: Normally, Let’s Encrypt uses an HTTP-01 challenge, where Let’s Encrypt servers attempt to contact your domain over port 80 to verify domain ownership. Because our container lives on a private Tailscale IP (100.x.y.z), the public internet cannot reach port 80, causing standard verification to fail.
    • The solution: The DNS-01 challenge proves domain ownership by creating a temporary TXT record in your Cloudflare DNS via the Cloudflare API. Let’s Encrypt queries public DNS servers instead of pinging your private network. You get a publicly trusted SSL certificate without exposing any ports.

1. Enable TUN Device on Proxmox Host

By default, unprivileged Proxmox LXC containers are isolated from the host’s /dev/net/tun network device. Tailscale requires this TUN interface to create its encrypted WireGuard network interface.

  1. Stop the target LXC container.
  2. Open your Proxmox host shell:
nano /etc/pve/lxc/<CT_ID>.conf
  1. Append these lines at the bottom of the config to pass through the TUN character device:
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
  1. Start the container back up:
pct start <CT_ID>

2. Install Dokploy & Tailscale in the LXC

Drop into your LXC shell (via SSH or the Proxmox web console):

Install Dokploy:

curl -sSL https://dokploy.com/install.sh | sh

Dokploy will automatically install Docker, Traefik, and all necessary background dependencies.

Install & Authenticate Tailscale:

curl -fsSL https://tailscale.com/install.sh | sh
tailscale up

Follow the authentication link in your terminal to log in and join the container to your Tailnet.

Grab your container’s Tailscale IPv4 address:

tailscale ip -4

(Keep this IP handy, for example: 100.x.y.z. This is your container’s private address within your Tailnet.)


3. Configure Cloudflare DNS & API Token

Since Traefik and Tailscale live on the same host inside the LXC, you do not need complex Tailscale subnet routing. You can point your domain directly to the container’s Tailscale IP.

A. Add DNS Record

  • Go to your Cloudflare dashboard > DNS > Records.
  • Create an A Record:
    • Name: Your app subdomain (such as app or a wildcard like *.yourdomain.com)
    • IPv4 Address: Your container’s Tailscale IP (100.x.y.z)
    • Proxy Status: DNS Only (Gray Cloud)

Important: Cloudflare Proxy (Orange Cloud) must be disabled. Cloudflare’s edge proxy cannot route traffic into private CGNAT IP ranges (100.64.0.0/10) used by Tailscale.

B. Generate Cloudflare API Token

Traefik needs scoped permissions to create and remove TXT records during the ACME DNS-01 challenge.

  • In Cloudflare, go to My Profile > API Tokens > Create Token.
  • Select the Edit zone DNS template.
  • Under Zone Resources, select Include > Specific zone > select your domain.
  • Create and copy the generated token.

4. Configure Traefik DNS-01 Challenge via Dokploy UI

Now instruct Traefik to use the Cloudflare API for certificate verification instead of HTTP:

  1. Open Dokploy in your browser at http://<TAILSCALE_IP>:3000 from any device connected to your Tailnet.

  2. Navigate to Web Server in the left sidebar.

  3. Under the Traefik section:

    • Environment Variables: Add your Cloudflare token:

      CF_DNS_API_TOKEN=your_cloudflare_api_token_here
    • Traefik Configuration: Ensure the certificatesResolvers block defines Cloudflare as the DNS challenge provider:

      certificatesResolvers:
        letsencrypt:
          acme:
            email: your-email@domain.com
            storage: /etc/dokploy/traefik/dynamic/acme.json
            dnsChallenge:
              provider: cloudflare
              resolvers:
                - "1.1.1.1:53"
                - "8.8.8.8:53"
  4. Click Save and Reload Traefik.

Sanity Check: Verify Traefik picked up the environment variable by running this command inside the LXC:

docker exec -it dokploy-traefik env | grep CF_DNS

It should return your CF_DNS_API_TOKEN.


5. Map Domain in Your Dokploy App

Now whenever you spin up a project or container in Dokploy, Traefik will handle the SSL handshake seamlessly under the hood:

  1. Go to your project/application in Dokploy > Domains tab.
  2. Click Add Domain:
    • Host: app.yourdomain.com
    • Path: /
    • Port: Container internal port (such as 3000 or 8080)
    • HTTPS: Toggle ON
  3. Click Save / Deploy.

Traefik will automatically communicate with Cloudflare via the API, complete the DNS-01 verification, and obtain a valid Let’s Encrypt certificate.

Open https://app.yourdomain.com from any device connected to your Tailnet. You will see the clean padlock icon, full HTTPS security, zero self-signed browser warnings, and end-to-end encrypted routing through Tailscale.