This repo contains a single Bash script that bootstraps a Traefik v3 reverse proxy with automatic HTTPS (Let's Encrypt) and runs Kiloview KiloLink Server Pro (KLSP) behind it. It also fixes terminal line editing (backspace/arrows) for the interactive prompts.
Tested on modern Linux distributions with Docker Engine and either the Docker Compose plugin (
docker compose) or the legacy binary (docker-compose).
What the script does
- Detects
docker composevsdocker-composeand uses whichever exists. - Ensures interactive prompts support backspace/arrow keys.
- Asks you a few values (domain, email, ports, image tag).
- Writes the following in your current directory:
.env— values entered at the prompts.docker-compose.yml— services for Traefik and KLSP.traefik/acme.json— Let's Encrypt certificate storage (0600 perms).traefik/dynamic/kls.yml— Traefik file-provider route for KLSP.kilolink-server/— persistent data directory for KLSP.
- Starts everything with Docker Compose.
- Prints the URLs for KLSP and the Traefik dashboard when done.
KLSP runs with
network_mode: hostas required by the image. Traefik publishes 80/tcp and 443/tcp to the host for ACME and HTTPS.
Prerequisites
- Linux host with sudo/root.
- Docker Engine installed and running.
- Docker Compose — either the plugin (
docker compose) or legacy (docker-compose). - Public DNS A/AAAA records:
DOMAIN→ your server’s public IP (for examplewww.example.com → 203.0.113.10).- Optional dashboard:
traefik.DOMAIN→ same IP.
- Ports 80 and 443 open on the server and any upstream firewall/security group.
- If you’re using a CDN/proxy (e.g., Cloudflare), disable the orange cloud (no proxy) for initial issuance with the HTTP-01 challenge, or switch to DNS-01 (not configured by this script).
The script can add your user to the
dockergroup when run as root if Docker isn’t accessible for the owner user.
Quick start
- Save the script (e.g.,
bootstrap.sh) into an empty project folder. - Make it executable:
chmod +x bootstrap.sh
- Run it:
./bootstrap.sh
- Answer the prompts. Typical example:
- Domain for KLSP (FQDN):
kls.example.com - Let's Encrypt email:
admin@example.com - KLSP http local web access port (web_port):
83 - Aggregation port(s) for KiloLink (klnl_port):
50000,50001 - KLSP image tag:
latest - Public IP or DDNS devices will reach: press Enter to reuse the domain
- Domain for KLSP (FQDN):
- Wait for containers to start. When complete you’ll see:
- KLSP via Traefik:
https://kls.example.com - Traefik dashboard:
https://traefik.kls.example.com(replace with your domain)
- KLSP via Traefik:
If certificate issuance stalls, check:
docker logs -f traefik
Prompt reference
| Prompt | What it sets | Notes |
|---|---|---|
| Domain for KLSP | DOMAIN |
FQDN that points to this host. |
| Let's Encrypt email | LE_EMAIL |
ACME notifications & rate-limit identity. |
| KLSP http local web access port | WEB_PORT |
KLSP listens on this host port (defaults to 83). |
| Aggregation port(s) for KiloLink | KLNL_PORT |
Single port or comma list (e.g., 50000,50001). |
| (auto) | SERVER_PORT / STREAM_SERVER_PORT |
If you input exactly two klnl ports, the script maps them to these legacy variables for compatibility. |
| KLSP image tag | KLS_TAG |
e.g., latest or a version like vX.Y.Z. |
| Public IP or DDNS devices will reach | PUBLIC_IP |
Defaults to DOMAIN. Used for device dialing. |
All values are written to .env and expanded into docker-compose.yml and Traefik files.
Files generated
.
├── .env
├── docker-compose.yml
├── kilolink-server/
└── traefik/
├── acme.json (0600)
└── dynamic/
└── kls.yml
- Traefik performs HTTPS termination and routes
https://DOMAINto KLSP’s local web port viahost.docker.internal:WEB_PORT. - The dashboard is exposed at
https://traefik.DOMAIN(no auth by default — see Hardening).
Operating the stack
From the project directory:
- Start (already done by the script):
docker compose up -d
- View running containers:
docker compose ps
- Tail logs:
docker logs -f traefik docker logs -f klnksvr-pro
- Stop:
docker compose down
- Update KLSP image (e.g., change tag):
- Edit
.env→KLS_TAG=vX.Y.Z docker compose pull kls && docker compose up -d
- Edit
Using a custom SSL certificate instead of Let’s Encrypt (optional)
If you already have a certificate/key for DOMAIN and want Traefik to use them:
- Place your files in
traefik/certs/(create the folder):fullchain.pem(certificate chain)privkey.pem(private key)
- Create
traefik/dynamic/certs.ymlwith:tls: certificates: - certFile: /etc/traefik/certs/fullchain.pem keyFile: /etc/traefik/certs/privkey.pem
- Mount the certs folder and the extra dynamic file by editing
docker-compose.yml→traefikservice:volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik/acme.json:/acme/acme.json - ./traefik/dynamic:/etc/traefik/dynamic:ro - ./traefik/certs:/etc/traefik/certs:ro
- (Optional) Comment out or remove the
--certificatesresolvers.le.acme.*lines undertraefik.commandto avoid ACME entirely. - Apply changes:
docker compose up -d
Traefik prefers the certificate that matches the SNI. If a static
tls.certificatesentry matches your domain, it will serve that cert.
Hardening tips
- Protect the Traefik dashboard: add Basic Auth middleware and/or IP allowlist. Example dynamic file
traefik/dynamic/dashboard.yml:Generate a hash withhttp: middlewares: dash-auth: basicAuth: users: - "admin:$$apr1$$QX3...<htpasswd hash here>" routers: dashboard: rule: "Host(`traefik.${DOMAIN}`)" entryPoints: ["websecure"] service: "api@internal" tls: certResolver: le middlewares: ["dash-auth"]
htpasswd -nb admin 'yourpassword'. - Consider enabling HTTP/3/QUIC by uncommenting the
443/udpmapping indocker-compose.yml. - Keep
traefik/acme.jsonat permission0600. - Restrict SSH and keep the system updated.
Troubleshooting
- ACME/Let’s Encrypt fails
- DNS A/AAAA record doesn’t point to this host. Fix DNS and wait for propagation.
- Port 80/tcp not reachable from the Internet. Open/firewall/NAT as required.
- CDN proxy is on (e.g., Cloudflare orange cloud). Turn off proxy or switch to DNS-01.
ERROR: user is not in the 'docker' group
Follow the script’s printed instructions:sudo usermod -aG docker <your-user> newgrp docker
- Port already in use (
80/443/WEB_PORT)
Stop the conflicting service or change the port value before re-running. - Cannot reach KLSP UI through Traefik
ConfirmWEB_PORTis correct and that KLSP is listening locally, then checktraefik/dynamic/kls.ymltarget URL.
Uninstall / cleanup
From the project directory:
docker compose down -v
sudo rm -rf traefik kilolink-server docker-compose.yml .envFAQ
Q: Does the script fix the backspace issue during prompts?
A: Yes. It restores a sane TTY and sets the erase character so backspace and arrow keys work in most shells/terminals.
Q: Which ports must I open to the Internet?
A: TCP 80 and 443 for Traefik. Your aggregation ports (e.g., 50000,50001) must also be reachable from your devices as required by KLSP.
Q: Can I run behind NAT?
A: Yes, as long as the public IP/hostname you give to devices forwards the necessary ports to this host.
Q: Can I keep using Let’s Encrypt after adding a custom cert?
A: You can keep ACME config present; Traefik will serve the static cert when it matches the SNI. You can also remove ACME entirely if you prefer.
Support
- Check container logs first:
docker logs -f traefikanddocker logs -f klnksvr-pro. - If you need to adjust behavior, edit
.env,docker-compose.yml, or files intraefik/dynamic/, thendocker compose up -d.
TLDR
Install Docker Container for Ubuntu and make sure you do the following ( ) means the user accountname
sudo usermod -aG docker <your-user>
newgrp dockercreate a product folder make sure you grand chmod 755 to the folder before putting klsp_ssl_jambantek.sh into it
mkdir project
sudo chmod 755 projectdownload the klsp_ssl_jambantek.sh file and upload into your Ubuntu Server /project ( tested on Ubuntu Server 24.04 LTS )
wget -O klsp_ssl_jamtanket.sh \
https://raw.githubusercontent.com/jumundz/klsp-traefik-ssl/main/klsp_ssl_jamtanket.shsudo chmod +x klsp_ssl_jambantek.shor you can run the following script
/bin/bash <( curl https://raw.githubusercontent.com/jumundz/klsp-traefik-ssl/refs/heads/main/klsp_ssl_jambantek.sh)If you have error says ("ERROR: Docker Compose not found (neither 'docker compose' nor 'docker-compose').
sudo apt install docker-compose Make sure you have a Dynamic DNS or Domain Name pointed to your on-prom public internet ( no-ip.org ) example.
Answer the prompts during installation. Typical example:
- Domain for KLSP (FQDN):
kls.example.com - Let's Encrypt email:
admin@example.com - KLSP http local web access port (web_port):
83please do not use port 80 - Aggregation port(s) for KiloLink (klnl_port):
50000,50001 - KLSP image tag:
latest - Public IP or DDNS devices will reach: press Enter to reuse the domain ( e.g : // you on prep reachable IP address behind a NAT. for instance 192.168.1.XXX )
Once Installation Complete you should test the KLSP is running : Navigate to the Local IP Address 192.168.1.XXX:83 < if you have change the port to others please use it else the defalt web_port should be 83
your local on-premp with SSL is ready to go.
Make sure you portfoward all the necessary port to your Local KLSP Server
- 50000:50001 UDP
- 80 TCP
- 443 TCP
- 30000:30300 UDP / TCP
NO NDI HX PLUGIN Installed in this .sh file
Please check out KLSP installation guide to find out MORE