Vaultwarden on Tailscale SSL not persisting
Posted by paulrturnbull
Hi Tom, I had Vaultwarden up and working previously but have lost it again. Tried with Tom AI to resolve it but having trouble. Tom AI chat inline below Cheers, Paul 🔧 working on your SparkBox… Container's up and healthy — and the logs I already have show it restarted ~8 minutes ago and came up clean on 1.36.0. So the container itself is fine. What specifically isn't working? A few common ones: 1. Can't log in to the vault — Vaultwarden only works on an https:// URL. Plain http:// will get refused by the Bitwarden clients. Easiest fix: use the Bitwarden browser extension or mobile app and point it at your NAS IP on port 8222 — they don't need HTTPS. 2. Admin panel not accessible — hit http://<NAS-IP:8222/admin and use the admin token from Settings → Passwords in the SparkBox dashboard. 3. Browser extension / app says "invalid URL" or won't connect — make sure you're entering the server as http://<NAS-IP:8222 (no trailing slash, no /vault). 4. Domain-based access failing (https://vault.yourdomain.com) — that needs NPM wired up with a valid SSL cert. If DNS isn't pointing at your box yet, the cert won't issue. Which of those matches what you're seeing? ↗ Didn’t fully fix it? Share to demox so Tom can ship an update an error has occured failed to fetch 🔧 working on your SparkBox… 🔧 working on your SparkBox… Container is healthy and running fine. The "An error has occurred. Failed to fetch" is a client-side error, not a server crash. Most likely cause: the DOMAIN setting in Vaultwarden's config doesn't match the URL you're actually using to access it. The logs show DOMAIN is being set via the admin panel config.json — if that domain doesn't match where the Bitwarden client is trying to connect, you get exactly this error. A few things to check: 1. How are you accessing it? Direct IP (http://<NAS-IP:8222) or via a domain (https://vault.yourdomain.com)? Tell me which and I can narrow it down fast. 2. If via a domain — go to http://<NAS-IP:8222/admin, scroll down to General Settings → Domain URL and make sure it exactly matches the URL you're hitting (including https:// and no trailing slash). 3. If via direct IP — make sure you're using http:// not https://. Vaultwarden on direct IP doesn't have a cert, so the Bitwarden clients will refuse https:// and throw "failed to fetch". 4. Which client? Browser web vault, browser extension, or mobile app? The web vault (http://<NAS-IP:8222) is the strictest — extensions and mobile apps are more forgiving. What URL are you hitting it from? ↗ Didn’t fully fix it? Share to demox so Tom can ship an update https://paul-t5610.tail40db03.ts.net/ 🔧 working on your SparkBox… The logs confirm it — Vaultwarden is saving its DOMAIN in data/config.json and that's overriding whatever's in .env. If that saved domain doesn't match your Tailscale URL, the Bitwarden clients throw "failed to fetch" on anything that requires WebSocket or CORS. Fix: 1. Go to http://paul-t5610.tail40db03.ts.net:8222/admin (over Tailscale) 2. Log in with your admin token (SparkBox dashboard → Settings → Passwords) 3. General Settings → Domain URL — set it to exactly: https://paul-t5610.tail40db03.ts.net:8222 4. Hit Save at the bottom Then reload the web vault and try again. The domain needs to include the port since you're not going through NPM on 443. One thing worth noting: Tailscale MagicDNS URLs get automatic HTTPS via Tailscale's own certs, so https:// should work fine over the tunnel. If the Bitwarden client still complains after updating the domain, try accessing it as http:// first just to confirm connectivity, then switch back to https://. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update unable to save config DOMAIN needs Yeah that's the classic one — Vaultwarden's admin page enforces that DOMAIN must be a proper base URL with no path, and it's picky about format. Try setting it to exactly: https://paul-t5610.tail40db03.ts.net No port, no trailing slash. Then save again. The reason: Tailscale's HTTPS proxy handles port 443 transparently for MagicDNS hostnames — you don't need :8222 in the domain value. The port is only for the browser to reach the admin page directly, not what Vaultwarden stores as its own identity. If it still rejects it, paste the exact full error message — it usually tells you exactly which validation rule it's hitting. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update This site can’t be reached The web page at https://paul-t5610.tail40db03.ts.net/ might be temporarily down or it may have moved permanently to a new web address. ERRSSLUNRECOGNIZEDNAMEALERT That's a Tailscale HTTPS issue, not Vaultwarden. ERRSSLUNRECOGNIZEDNAMEALERT means Tailscale's cert doesn't cover that hostname — the TLS handshake is failing before Vaultwarden even sees the request. Two things to check: 1. HTTPS not enabled on that device in Tailscale — go to the Tailscale admin console, find paul-t5610, and make sure HTTPS is enabled for it. It's a per-machine toggle under the machine's settings (three-dot menu → Enable HTTPS). 2. MagicDNS not enabled on your tailnet — Tailscale admin → DNS tab → make sure MagicDNS is on AND "Enable HTTPS" is toggled at the tailnet level. Once HTTPS is enabled for that machine, Tailscale provisions a Let's Encrypt cert for it automatically. Takes about 30 seconds. After that, try https://paul-t5610.tail40db03.ts.net again — no port needed, Tailscale proxies 443 for you. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update no HTTPS toggle under the 3 dots for the machine Yeah, the per-machine HTTPS toggle only appears if tailnet-wide HTTPS is enabled first. That's the missing step. In the Tailscale admin console: 1. Go to DNS tab (left sidebar) 2. Scroll down to HTTPS Certificates 3. Hit Enable HTTPS 4. Also confirm MagicDNS is on while you're there Once you save that, go back to Machines, find paul-t5610, three-dot menu — the HTTPS toggle should appear now. Enable it there too. Then give it 30-60 seconds for the cert to provision and try https://paul-t5610.tail40db03.ts.net again. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update HTTPS is already enabled and magidns enabled 🔧 working on your SparkBox… Tailscale container is up and healthy. So the issue is almost certainly the cert provisioning step. SSH into the box and run: sudo tailscale cert paul-t5610.tail40db03.ts.net Paste back what it says — that'll tell us if the cert is missing, expired, or if there's a permission issue. That's almost certainly the root cause of ERRSSLUNRECOGNIZEDNAMEALERT. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update pturnbull@paul-T5610:~$ sudo tailscale cert paul-t5610.tail40db03.ts.net [sudo] password for pturnbull: Public cert unchanged at paul-t5610.tail40db03.ts.net.crt Private key unchanged at paul-t5610.tail40db03.ts.net.key pturnbull@paul-T5610:~$ 🔧 working on your SparkBox… Logs look healthy — connected, no errors. The issue is that Tailscale Serve isn't configured, so nothing is listening on port 443 for that hostname inside the container. SparkBox's Tailscale module uses tailscale serve to proxy HTTPS → your apps. Run this on the host to check what's currently configured: sudo tailscale serve status If it comes back empty or "No serve config", that's the problem — Serve isn't set up. SparkBox should have configured this automatically, but something may have reset it. Paste the output and I'll tell you exactly what's missing. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update Private key unchanged at paul-t5610.tail40db03.ts.net.key pturnbull@paul-T5610:~$ sudo tailscale serve status No serve config pturnbull@paul-T5610:~$ Yeah, that's it. Serve config got wiped — nothing is proxying HTTPS to your apps. SparkBox re-applies its Tailscale serve config when the sb-tailscale container restarts. So the quickest fix is to restart the Tailscale module — want me to do that now? ↗ Didn’t fully fix it? Share to demox so Tom can ship an update yes 🔧 Tom AI wants to: Restart the tailscale module ✓ Ran — see the result below. Lost the connection to SparkBox mid-reply — it’s reconnecting. Resend your message in a moment. pturnbull@paul-T5610:~$ sudo tailscale serve status [sudo] password for pturnbull: No serve config pturnbull@paul-T5610:~$ 🔧 working on your SparkBox… The logs don't show any serve config being applied on startup — SparkBox's serve setup script isn't running or isn't finding anything to configure. Check what's in the Tailscale serve config file on the host: cat /opt/sparkbox/data/tailscale/serve-config.json And also: ls /opt/sparkbox/modules/tailscale/ Paste both outputs — I want to see if SparkBox generated a serve config at all, and what scripts are in the module directory. This is starting to look like something Tom needs to see, so if we hit a dead end I'll flag it for the forum. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update pturnbull@paul-T5610:~$ cat /opt/sparkbox/data/tailscale/serve-config.json cat: /opt/sparkbox/data/tailscale/serve-config.json: No such file or directory pturnbull@paul-T5610:~$ pturnbull@paul-T5610:~$ ls /opt/sparkbox/modules/tailscale/ config docker-compose.yml serve.json pturnbull@paul-T5610:~$ There's a serve.json in the module directory — let's see what's in it: cat /opt/sparkbox/modules/tailscale/serve.json And also: cat /opt/sparkbox/modules/tailscale/docker-compose.yml | grep -A 20 entrypoint The serve config exists at the module level but clearly isn't getting applied to the running container. Want to see if it's being mounted/copied correctly. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update pturnbull@paul-T5610:~$ cat /opt/sparkbox/modules/tailscale/serve.json { "TCP": { "443": { "HTTPS": true } }, "Web": { "${TSCERTDOMAIN}:443": { "Handlers": { "/": { "Proxy": "http://127.0.0.1:8443" } } } } } pturnbull@paul-T5610:~$ cat /opt/sparkbox/modules/tailscale/docker-compose.yml | grep -A 20 entrypoint pturnbull@paul-T5610:~$ Right, so the serve.json is there and looks correct — it proxies https://<tailscale-hostname/ → http://127.0.0.1:8443 (your SparkBox dashboard). But there's no entrypoint in the compose file to apply it, which is why it never gets set. The ${TSCERTDOMAIN} variable also needs to be substituted before Tailscale can use it. Let's do this manually to confirm it works: sudo docker exec sb-tailscale tailscale serve set --bg --https=443 http://127.0.0.1:8443 Then check: sudo tailscale serve status Paste the output — if that works, it confirms the fix and we can figure out how to make it persist across restarts. This is also worth flagging to Tom since the auto-apply on startup isn't working. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update pturnbull@paul-T5610:~$ sudo docker exec sb-tailscale tailscale serve set --bg --https=443 http://127.0.0.1:8443 Error: invalid number of arguments (4) try tailscale serve --help for usage info pturnbull@paul-T5610:~$ Older Tailscale CLI syntax. Try this instead: sudo docker exec sb-tailscale tailscale serve --https=443 --bg http://127.0.0.1:8443 ↗ Didn’t fully fix it? Share to demox so Tom can ship an update pturnbull@paul-T5610:~$ sudo docker exec sb-tailscale tailscale serve --https=443 --bg http://127.0.0.1:8443 Available within your tailnet: https://paul-t5610-1.tail40db03.ts.net/ |-- proxy http://127.0.0.1:8443 Serve started and running in the background. To disable the proxy, run: tailscale serve --https=443 off pturnbull@paul-T5610:~$ That's working — but notice the hostname it gave you: paul-t5610-1.tail40db03.ts.net not paul-t5610.tail40db03.ts.net. The -1 suffix is because Tailscale picked a slightly different cert domain than expected. Try hitting https://paul-t5610-1.tail40db03.ts.net/ in your browser and see if it loads. If it does, that's your real Tailscale URL for this box. The serve config is live and working — the only remaining problem is it won't survive a container restart. That's worth flagging to Tom since the auto-apply on startup clearly isn't working. Hit the Share to demox button below so he can look at why serve.json isn't being applied on container start. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update it presents the soarkbox dashboard Nice, so HTTPS via Tailscale is working. Two things to note: 1. Your real Tailscale URL is https://paul-t5610-1.tail40db03.ts.net — bookmark that one, not the -1-less version. 2. This won't survive a container restart — next time sb-tailscale restarts, the serve config gets wiped and you're back to "No serve config". Hit the Share to demox button below so Tom can see why serve.json isn't being auto-applied on startup. That's a SparkBox bug — the module has the config file but nothing's wiring it into the running container. ↗ Didn’t fully fix it? Share to demox so Tom can ship an update
2 replies
tomspark wrote:
The Tom AI transcript confirms a real SparkBox bug: the Tailscale module has a serve config file but nothing applies it when the container starts, so your https:// access resets on any restart. Flagging this for a fix. Workaround until it ships: if sb-tailscale ever restarts, SSH in and run sudo docker exec sb-tailscale tailscale serve --https=443 --bg http://127.0.0.1:8443 to re-apply it. For Vaultwarden: now that your Tailscale is connected, you should be able to reach it at http://paul-t5610-1.tail40db03.ts.net:8222 from any device on your Tailscale network — the connection is encrypted end-to-end by Tailscale so https isn't needed for that.
paulrturnbull wrote:
Thanks Tom