Cloudflared is a lightweight, self-hosted dashboard for running and managing a Cloudflare Tunnel through the cloudflared binary.
It is designed for home server environments where you want a simple local Web UI to save a tunnel token, start or stop the tunnel, persist configuration, and automatically restore the tunnel after the container starts.
The application runs as a Docker container and stores persistent configuration inside /config.
- Self-hosted Web UI for Cloudflare Tunnel management.
- Token-based
cloudflared tunnel runworkflow. - Start and stop tunnel from the dashboard.
- Persistent configuration stored in
/config/config.json. - Auto-start support when a token is saved.
- Configurable tunnel protocol:
auto,http2, orquic. - Configurable region:
autoorus. - Optional metrics endpoint support.
- Toast notifications for all server actions (save, start, stop, restart).
- Keyboard shortcuts (
Ctrl+Enterto toggle tunnel,Ctrl+Lto open logs). - Connection health monitoring with "Connection lost" indicator.
- Production-ready Next.js standalone output.
- Docker-first deployment for home servers.
- GitHub Container Registry image publishing.
- Multi-architecture Linux container support.
- Code quality workflow for Prettier, ESLint, and TypeScript checks.
For Docker deployment:
- Docker Engine.
- Docker Compose.
- A Cloudflare Tunnel token.
- A Linux home server, VPS, NAS, or any Docker-capable machine.
For local development:
- Node.js 22 or newer.
- pnpm 11.6.0.
- Git.
Official container image:
ghcr.io/ptkelanatechsolutions/cloudflared
Recommended stable tag:
ghcr.io/ptkelanatechsolutions/cloudflared:1.8.3
Latest tag:
ghcr.io/ptkelanatechsolutions/cloudflared:latest
Pull the latest image:
docker pull ghcr.io/ptkelanatechsolutions/cloudflared:latestThe official container image supports Linux containers.
| Platform | Status | Notes |
|---|---|---|
linux/amd64 |
Supported | Intel/AMD 64-bit servers, VPS, mini PCs, and most home servers. |
linux/arm64 |
Supported | ARM64 servers, Raspberry Pi 4/5 64-bit, ARM VPS, and Apple Silicon Docker Desktop. |
linux/arm/v7 |
Supported | 32-bit ARMv7 devices such as Raspberry Pi OS 32-bit. |
| Host | Status | Notes |
|---|---|---|
| Linux | Recommended | Best target for home server deployments. |
| Windows | Supported via Docker Desktop Linux containers | Native Windows containers are not supported. |
| macOS | Supported via Docker Desktop Linux containers | Native macOS containers are not supported. |
- Native Windows containers.
- Native macOS containers.
linux/386.linux/arm/v6.
Create a docker-compose.yml file:
services:
cloudflared-web:
image: ghcr.io/ptkelanatechsolutions/cloudflared:latest
container_name: cloudflared-web
restart: unless-stopped
# Recommended for Linux home server deployments.
# Do not use "ports" together with "network_mode: host".
network_mode: host
environment:
NODE_ENV: production
WEBUI_PORT: 23899
WEBUI_HOST: 0.0.0.0
CONFIG_DIR: /config
volumes:
- cloudflared-config:/config
volumes:
cloudflared-config:
name: cloudflared-configStart the container:
docker compose up -dOpen the Web UI:
http://SERVER_IP:23899
Example:
http://192.168.1.20:23899
docker run -d \
--name cloudflared-web \
--network host \
-v cloudflared-config:/config \
--restart unless-stopped \
ghcr.io/ptkelanatechsolutions/cloudflared:latestThen open:
http://SERVER_IP:23899
The default Compose example uses host networking, which is intended for Linux home server deployments.
If you are using Docker Desktop or an environment where host networking is not suitable, use port mapping instead.
services:
cloudflared-web:
image: ghcr.io/ptkelanatechsolutions/cloudflared:latest
container_name: cloudflared-web
restart: unless-stopped
ports:
- "23899:23899"
environment:
NODE_ENV: production
WEBUI_PORT: 23899
WEBUI_HOST: 0.0.0.0
CONFIG_DIR: /config
volumes:
- cloudflared-config:/config
volumes:
cloudflared-config:
name: cloudflared-configStart the container:
docker compose up -dOpen:
http://localhost:23899
The Dockerfile is located at:
docker/Dockerfile
Build locally:
docker build \
-f docker/Dockerfile \
-t cloudflared-web:local .Run the local image:
docker run -d \
--name cloudflared-web \
--network host \
-v cloudflared-config:/config \
--restart unless-stopped \
cloudflared-web:local| Variable | Default | Description |
|---|---|---|
WEBUI_PORT |
23899 |
Port used by the Web UI inside the container. |
WEBUI_HOST |
0.0.0.0 |
Host address used by the Next.js standalone server. |
CONFIG_DIR |
/config |
Directory used to persist token and tunnel settings. |
CLOUDFLARED_BIN |
cloudflared |
Optional override for the cloudflared binary path. |
NODE_ENV |
production |
Runtime mode for the web server. |
| Argument | Default | Description |
|---|---|---|
CLOUDFLARED_VERSION |
2026.6.0 |
Cloudflared release version installed into the image. Use a specific version for reproducible builds. |
Example:
docker build \
-f docker/Dockerfile \
--build-arg CLOUDFLARED_VERSION=2026.6.0 \
-t cloudflared-web:local .Cloudflared stores application config inside:
/config/config.json
This file may contain:
- Tunnel token.
- Tunnel protocol.
- Tunnel region.
- Edge IP version preference.
- Metrics settings.
- Auto-start setting.
Because the tunnel token is persisted in /config, protect the Docker volume and avoid exposing the Web UI publicly without additional access control.
| Setting | Values | Description |
|---|---|---|
protocol |
auto, http2, quic |
Controls the tunnel transport protocol. |
region |
auto, us |
Controls Cloudflare edge region preference. |
edgeIpVersion |
auto, 4, 6 |
Controls preferred edge IP version. |
metricsEnabled |
true, false |
Enables or disables cloudflared metrics. |
metricsPort |
1-65535 |
Port used by the cloudflared metrics endpoint. |
autoStart |
true, false |
Starts the tunnel automatically when the app boots and a token is saved. |
Install dependencies:
pnpm installStart development server:
pnpm devBuild production output:
pnpm buildRun lint:
pnpm lintRun type check:
pnpm typecheckCheck formatting:
pnpm format:checkFormat files:
pnpm formatCloudflared/
├── apps/
│ └── web/
│ ├── app/
│ ├── components/
│ ├── lib/
│ ├── public/
│ ├── next.config.ts
│ └── package.json
├── packages/
│ └── core/
│ └── src/
│ ├── cloudflared/
│ ├── config/
│ ├── schema/
│ └── index.ts
├── docker/
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── entrypoint.sh
├── .github/
│ └── workflows/
│ ├── code-quality.yml
│ └── container.yml
├── package.json
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
This repository includes two GitHub Actions workflows.
Runs formatting, linting, and type checking.
Checks:
- Prettier.
- ESLint.
- TypeScript.
Builds and publishes the Docker image to GitHub Container Registry.
The workflow runs when a SemVer tag without the v prefix is pushed:
1.0.0
1.0.1
1.1.0
Published image tags include:
ghcr.io/ptkelanatechsolutions/cloudflared:1.0.0
ghcr.io/ptkelanatechsolutions/cloudflared:latest
Create a version tag without the v prefix:
git tag 1.0.0
git push origin 1.0.0The container workflow will build and publish the image automatically.
- Keep your Cloudflare Tunnel token private.
- The token is persisted in the
/configDocker volume. - Do not expose the Web UI directly to the public internet without authentication or network-level protection.
- Prefer running the dashboard on a trusted LAN, VPN, or protected reverse proxy.
- Keep the container image and
cloudflaredbinary up to date.
This project is licensed under the MIT License.
See the LICENSE file for details.
