Fixing Planka WebSocket Issues with Tailscale

Fixing Planka WebSocket Issues with Tailscale Integration

Fixing Planka WebSocket Issues with Tailscale Integration

This writeup documents the complete solution for resolving WebSocket connection failures in Planka when accessed through Tailscale, including CORS configuration and proper proxy setup.

Problem

Planka was experiencing WebSocket connection failures with errors like:

WebSocket connection to 'wss://TAILSCALE_URL/socket.io/?__sails_io_sdk_version=1.2.1&__sails_io_sdk_platform=node&__sails_io_sdk_language=javascript&EIO=3&transport=websocket' failed

The application would load but remain stuck in a loading state due to failed WebSocket connections when accessed through Tailscale.

Root Cause

The issue was caused by:

  1. Incorrect BASE_URL configuration - pointing to wrong port

  2. CORS restrictions - Sails.js only allowing localhost origins

  3. Missing proxy trust configuration for Tailscale

Solution Overview

The fix involves configuring Planka's CORS settings to accept connections from any origin and setting up proper proxy trust for Tailscale, along with ensuring the BASE_URL matches the Tailscale endpoint.

Step-by-Step Solution

1. Configure Docker Compose Environment Variables

Edit /opt/planka/docker-compose.yml and ensure the environment section includes:

Key changes:

  • BASE_URL must match your Tailscale hostname

  • TRUST_PROXY=true enables proxy support

  • SAILS_SECURITY_CORS_ALLOW_ORIGINS=* allows all origins

  • SAILS_SECURITY_CORS_ALLOW_ANY_ORIGIN_WITH_CREDENTIALS_UNSAFE=true enables credentials with wildcard origin

2. Apply Configuration Changes

3. Configure Tailscale Serve

Set up Tailscale to serve Planka on HTTPS in background:

4. Restart Planka

Apply the configuration changes by restarting the containers:

5. Verify Setup

Check that everything is running correctly:

Final Configuration

Docker Compose Environment Variables

Tailscale Configuration

Port Configuration

Access URLs

Local Access

  • URL: http://localhost:3900

  • Use case: Development and local testing

Remote Access (Tailscale)

  • URL: https://TAILSCALE_URL

  • Requirements:

    • Tailscale installed on client machine

    • Connected to same tailnet

    • HTTPS enabled automatically

Key Technical Details

CORS Configuration

The critical fix was enabling CORS for all origins in Sails.js:

WebSocket Support

Sails.js requires specific CORS configuration to allow WebSocket connections from external domains. The environment variables SAILS_SECURITY_CORS_ALLOW_ORIGINS=* and SAILS_SECURITY_CORS_ALLOW_ANY_ORIGIN_WITH_CREDENTIALS_UNSAFE=true override the default localhost-only restriction.

Tailscale Proxy

Tailscale serve acts as an HTTPS proxy, forwarding requests from the public Tailscale URL to the local Planka instance. The TRUST_PROXY=true setting tells Planka to trust the proxy headers from Tailscale.

Security Considerations

⚠️ Important: The configuration allowOrigins: '*' and allowAnyOriginWithCredentialsUnsafe: true allows connections from any domain. This is acceptable for Tailscale since:

  1. Tailscale provides network-level security through its VPN

  2. Access is restricted to your tailnet members

  3. The service is not exposed to the public internet

For production deployments on public networks, consider restricting allowOrigins to specific trusted domains.

Troubleshooting

Common Issues

WebSocket still failing after configuration:

Tailscale serve not working:

Container unhealthy:

Verification Commands

Use these commands to verify the complete setup:

Alternative Solutions

If the above solution doesn't work, consider these alternatives:

1. File-based Configuration Override

Create custom config/sockets.js and config/security.js files and mount them as volumes (requires Docker file sharing configuration on macOS).

2. Environment Variable Method

Use Sails.js environment variable overrides for more granular control:

3. Reverse Proxy Headers

If using nginx or another reverse proxy, add WebSocket upgrade headers:


Summary

The solution successfully resolves Planka WebSocket issues by:

  1. Configuring proper CORS settings via environment variables

  2. Setting correct BASE_URL to match Tailscale endpoint

  3. Enabling proxy trust for Tailscale forwarding

  4. Running Tailscale serve in background for persistent access

Final Result:

  • βœ… Local access: http://localhost:3900

  • βœ… Remote access: https://TAILSCALE_URL

  • βœ… WebSocket connections working correctly

  • βœ… Full functionality available from any device in tailnet

Environment: macOS + Docker + Tailscale Planka Version: 2.0.0-rc.3

Last updated