Skip to content

Installation

Install the edge first, then the client. The edge is the security boundary, so avoid per-client overrides for daemon config in production.

Install flow diagram

From the repo root:

Terminal window
make build

This creates:

  • bin/mytunnel
  • bin/mytunneld

Without local Go, build in Docker:

Terminal window
mkdir -p bin
docker run --rm -v "$PWD":/workspace -w /workspace golang:1.25 \
sh -lc 'export PATH=/usr/local/go/bin:$PATH; go build -o bin/mytunnel ./cmd/mytunnel && go build -o bin/mytunneld ./cmd/mytunneld'

Create a wildcard record for the base domain:

*.tunnel.example.com -> <EDGE_IP>

Also keep the apex or a health hostname available for checking the edge:

edge-health.tunnel.example.com -> <EDGE_IP>

If you want Caddy to issue wildcard certificates, build or install Caddy with the DNS module for the provider that hosts your DNS zone.

Common module names:

ProviderCaddy DNS module
Cloudflaredns.providers.cloudflare
Route53dns.providers.route53
Google Cloud DNSdns.providers.googleclouddns
DigitalOceandns.providers.digitalocean
OVHdns.providers.ovh
Infomaniakdns.providers.infomaniak

Build Caddy with a provider module:

Terminal window
xcaddy build --with MODULE_PATH@latest
sudo install -m 0755 ./caddy /usr/bin/caddy

Minimal Caddyfile shape:

{
admin 127.0.0.1:2019
acme_dns <provider> {env.<PROVIDER_TOKEN_ENV>}
}
edge-health.tunnel.example.com {
respond "mytunnel edge is online" 200
}

Validate and restart Caddy:

Terminal window
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl restart caddy

Install the edge with Infomaniak Caddy bootstrap

Section titled “Install the edge with Infomaniak Caddy bootstrap”

On an apt-based edge server:

Terminal window
cd ~/tunneled
sudo ./scripts/install-edge.sh \
--base-domain tunnel.example.com \
--binary ./bin/mytunneld \
--infomaniak-token '<INFOMANIAK_API_TOKEN>'

This script:

  • Installs base packages with apt-get.
  • Builds Caddy with the Infomaniak DNS module if needed.
  • Writes /etc/caddy/Caddyfile.
  • Writes a restricted systemd drop-in for INFOMANIAK_API_TOKEN when provided.
  • Calls scripts/bootstrap-edge.sh.
  • Starts Caddy and mytunneld.

If you need a different Caddy provider, skip Caddy and bootstrap only the daemon:

Terminal window
sudo ./scripts/install-edge.sh \
--base-domain tunnel.example.com \
--binary ./bin/mytunneld \
--skip-caddy

Use this when Caddy is already installed and configured:

Terminal window
sudo ./scripts/bootstrap-edge.sh tunnel.example.com ./bin/mytunneld

Useful flags:

FlagMeaning
--run-user <user>systemd runtime user, default mytunnel
--run-group <group>runtime group, default primary group of the run user
--no-create-userfail instead of creating the runtime user

Bootstrap writes /etc/mytunneld/mytunneld.env with restricted permissions and installs /usr/local/bin/mytunneld.

On the source machine:

Terminal window
./scripts/install-local.sh --binary ./bin/mytunnel

Compatibility wrapper:

Terminal window
./scripts/install-client.sh ./bin/mytunnel

Both paths install /usr/local/bin/mytunnel.

For a dedicated tunnel user:

Terminal window
sudo ./scripts/install-edge-ssh-key.sh mytunnel-client ./id_ed25519.pub

The installer writes an authorized_keys entry with:

  • command="/usr/local/libexec/mytunnel-ssh-gate.sh"
  • no-agent-forwarding
  • no-X11-forwarding
  • no-user-rc
  • no-pty
  • permitlisten="127.0.0.1:*"

It also adds the SSH user to the daemon run group so control commands can read config and update the SQLite DB.

After SSH config changes, confirm AllowTcpForwarding yes and reload sshd.

Edge:

Terminal window
sudo ./scripts/check-edge.sh

Client:

Terminal window
./scripts/check-client.sh --edge mytunnel-client@edge.example.com

Daemon health:

Terminal window
mytunneld ctl health --json