I would like to share an AI generated script that I successfully used to automate my TrueNAS certificates with Tailscale.
This guide shows how to automatically use a Tailscale HTTPS certificate for the TrueNAS SCALE Web UI, when Tailscale runs inside a Docker container.
Overview
What this does
-
Runs
tailscale certinside a Docker container -
Writes the cert/key to a host bind-mount
-
Imports the cert into TrueNAS
-
Applies it to the Web UI
-
Restarts the UI
-
Runs automatically via cron
Requirements
-
TrueNAS SCALE
-
Docker
-
A running Tailscale container (
tailscaled) -
A host directory bind-mounted into the container at
/certs
Step 1 – Create a certificate directory on the host
Create a dataset or directory on your pool:
mkdir -p /mnt/<pool>/Applications/tailscale-certs
chmod 700 /mnt/<pool>/Applications/tailscale-certs
Step 2 – Bind-mount it into the Tailscale container
Your Tailscale container must mount the host directory to /certs. This can be done by editing the Tailscale App and adding a Host Path.
Conceptually:
Host path: /mnt/<pool>/Applications/tailscale-certs
Container path: /certs
This is required so the TrueNAS host can read the files generated by tailscale cert.
Step 3 – Create the automation script (generic)
Save this as:
/mnt/<pool>/scripts/import_tailscale_cert.sh
Script
#!/bin/bash
set -euo pipefail
# =========================
# USER CONFIG (REQUIRED)
# =========================
CONTAINER_NAME="__TAILSCALE_CONTAINER_NAME__"
TS_HOSTNAME="__TAILSCALE_DNS_NAME__"
HOST_CERT_DIR="__HOST_CERT_DIR__"
LOG_FILE="__LOG_FILE__"
TRUENAS_CERT_NAME="__TRUENAS_CERT_NAME__"
# =========================
CRT="${HOST_CERT_DIR}/ts.crt"
KEY="${HOST_CERT_DIR}/ts.key"
# Cron-safe PATH
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Log from inside the script (cron may discard output)
mkdir -p "$(dirname "$LOG_FILE")"
touch "$LOG_FILE"
exec >>"$LOG_FILE" 2>&1
echo "----- $(date -Is) starting Tailscale cert import -----"
# Dependency checks
command -v docker >/dev/null || { echo "ERROR: docker not found"; exit 2; }
command -v jq >/dev/null || { echo "ERROR: jq not found"; exit 2; }
command -v midclt >/dev/null || { echo "ERROR: midclt not found"; exit 2; }
# Ensure container is running
docker ps --format '{{.Names}}' | grep -qx "$CONTAINER_NAME" || {
echo "ERROR: container not running: $CONTAINER_NAME"
exit 2
}
# Ensure /certs mount exists
docker exec "$CONTAINER_NAME" sh -lc 'test -d /certs' || {
echo "ERROR: /certs not mounted in container"
exit 2
}
# Request or renew certificate
docker exec "$CONTAINER_NAME" sh -lc \
"tailscale cert --cert-file /certs/ts.crt --key-file /certs/ts.key \"$TS_HOSTNAME\""
# Verify files on host
[[ -s "$CRT" && -s "$KEY" ]] || {
echo "ERROR: certificate files missing on host"
exit 2
}
# Import into TrueNAS certificate store
midclt call certificate.create "$(jq -n \
--arg n "$TRUENAS_CERT_NAME" \
--rawfile c "$CRT" \
--rawfile k "$KEY" \
'{name:$n, create_type:"CERTIFICATE_CREATE_IMPORTED", certificate:$c, privatekey:$k}')" >/dev/null || true
# Look up certificate ID by name (robust across TrueNAS versions)
CERT_ID="$(midclt call certificate.query | jq -r \
--arg n "$TRUENAS_CERT_NAME" '.[] | select(.name==$n) | .id' | tail -n 1)"
[[ -n "$CERT_ID" ]] || {
echo "ERROR: failed to locate imported certificate"
exit 2
}
# Apply certificate to Web UI and restart UI
midclt call system.general.update "$(jq -n --argjson id "$CERT_ID" \
'{ui_certificate:$id, ui_restart_delay:1}')" >/dev/null
midclt call system.general.ui_restart >/dev/null
echo "SUCCESS: Web UI certificate updated"
Step 4 – Make the script executable
chmod 700 /mnt/<pool>/scripts/import_tailscale_cert.sh
Step 5 – Run once manually
/usr/bin/bash /mnt/<pool>/scripts/import_tailscale_cert.sh
A short Web UI disconnect is expected.
Step 6 – Verify in the UI
-
System Settings → Certificates
-
System Settings → General → GUI → Web Interface HTTPS Certificate
Confirm the new certificate is selected.
Step 7 – Create the cron job
TrueNAS UI → System Settings → Advanced → Cron Jobs → Add
Command
/usr/bin/bash /mnt/<pool>/scripts/import_tailscale_cert.sh
You can find the script on my Github repository: