Overview
Tailscale integration provides seamless device enrollment and monitoring within Nexus Access Vault. Devices can be automatically enrolled in your Tailscale network, ensuring zero-trust connectivity with end-to-end encryption.
Prerequisites
- Tailscale account with API access
- OAuth client credentials from Tailscale admin console
- Tailscale auth key (for device enrollment)
- Supabase project with Edge Functions enabled
Configuration
Environment Variables
Configure the following environment variables for Tailscale integration:
# Tailscale OAuth Credentials
TAILSCALE_CLIENT_ID="your-oauth-client-id"
TAILSCALE_CLIENT_SECRET="your-oauth-client-secret"
# Tailscale Auth Key (for device enrollment)
TAILSCALE_AUTH_KEY="tskey-auth-xxxxxxxxxx"
Obtaining OAuth Credentials
- Log in to the Tailscale Admin Console
- Navigate to Settings → OAuth clients
- Click Generate OAuth client
- Select the following scopes:
devices:read - Read device information
devices:write - Manage devices
- Save the Client ID and Client Secret
Generating Auth Keys
- In the Tailscale Admin Console, go to Settings → Keys
- Click Generate auth key
- Configure the key:
- Reusable: Yes (for multiple device enrollments)
- Ephemeral: No (for persistent devices)
- Pre-authorized: Yes (auto-approve devices)
- Tags: Add tags like
tag:prod or tag:sap
- Copy the generated key
Tailscale API Edge Function
The Tailscale API integration is implemented as a Supabase Edge Function at:
supabase/functions/tailscale-api/index.ts
Available Actions
1. List Devices
Retrieve all devices in your Tailscale network:
const { data, error } = await supabase.functions.invoke('tailscale-api', {
body: {
action: 'list-devices'
}
});
if (data?.success) {
console.log('Devices:', data.devices);
}
2. Check Device Status
Check if a specific device is online:
const { data, error } = await supabase.functions.invoke('tailscale-api', {
body: {
action: 'check-device',
identifier: 'my-laptop' // hostname, name, or IP
}
});
if (data?.found && data?.online) {
console.log('Device is online:', data.device);
}
3. Generate Auth Key
Generate a Tailscale auth key for device enrollment:
const { data, error } = await supabase.functions.invoke('tailscale-api', {
body: {
action: 'generate-auth-key',
deviceId: 'uuid-of-device',
tags: ['tag:prod'],
group: 'sap'
},
headers: {
Authorization: `Bearer ${session.access_token}`
}
});
if (data?.success) {
console.log('Auth key:', data.authKey);
console.log('Expires at:', data.expiresAt);
}
4. Validate Enrollment
Validate that a device has successfully enrolled:
const { data, error } = await supabase.functions.invoke('tailscale-api', {
body: {
action: 'validate-enrollment',
deviceId: 'uuid-of-device',
hostname: 'my-laptop'
},
headers: {
Authorization: `Bearer ${session.access_token}`
}
});
if (data?.enrolled) {
console.log('Device enrolled successfully:', data.device);
}
5. Sync Devices
Sync Tailscale device status with local database:
const { data, error } = await supabase.functions.invoke('tailscale-api', {
body: {
action: 'sync-devices'
},
headers: {
Authorization: `Bearer ${session.access_token}`
}
});
console.log(`Synced ${data.synced} devices`);
Tailscale Monitor Component
The TailscaleMonitor component provides real-time monitoring of device connectivity:
Component Usage
import { TailscaleMonitor } from '@/components/devices/TailscaleMonitor';
function Dashboard() {
return (
<TailscaleMonitor
userId={user.id}
organizationId={profile.organization_id}
/>
);
}
Features
- Real-time Updates: Subscribes to device status changes via Supabase Realtime
- Connection Polling: Checks device connectivity every 30 seconds
- Status Indicators: Visual badges for online, offline, and pending devices
- Last Seen Tracking: Shows when devices were last active
- Manual Refresh: Button to force status update
Status States
status === 'active'
// Device is connected and online
// Shows green badge with CheckCircle icon
Device Enrollment Flow
Automatic Enrollment
- User registers a new device in the portal
- Portal calls
generate-auth-key action with device details
- Auth key is stored in device metadata
- User receives enrollment instructions with the auth key
- User runs Tailscale on their device:
tailscale up --authkey=tskey-auth-xxxxxxxxxx
- Portal validates enrollment with
validate-enrollment action
- Device status updates to “active” when connection confirmed
Database Schema
Device metadata stores Tailscale information:
interface DeviceMetadata {
tailscale_auth_key?: string;
tailscale_key_expires?: string;
tailscale_tags?: string[];
tailscale_group?: string;
tailscale_device_id?: string;
tailscale_hostname?: string;
tailscale_ip?: string;
tailscale_os?: string;
tailscale_online?: boolean;
tailscale_last_seen?: string;
}
Event Logging
All Tailscale operations are logged to the device_events table:
Auth Key Generated
await supabase.from('device_events').insert({
device_id: deviceId,
event_type: 'tailscale_auth_key_generated',
details: {
tags,
group,
expiresAt: authKey.expiresAt
},
});
Enrollment Complete
await supabase.from('device_events').insert({
device_id: deviceId,
event_type: 'tailscale_enrollment_complete',
details: {
tailscale_device_id: tailscaleDevice.id,
hostname: tailscaleDevice.hostname,
ip: tailscaleDevice.ipAddresses?.[0],
},
});
Security Considerations
Protect OAuth Credentials: Never expose your Tailscale Client ID and Client Secret in client-side code. These should only be stored as environment variables in your Edge Functions.
Best Practices
- Use Pre-authorized Keys: Enable pre-authorization to avoid manual approval
- Set Expiration: Configure auth keys to expire after 24 hours
- Apply Tags: Use Tailscale tags to enforce ACL policies
- Audit Logs: Review device_events table regularly
- Rotate Credentials: Periodically rotate OAuth client credentials
- Enable MFA: Require multi-factor authentication for Tailscale admin access
ACL Configuration
Configure Tailscale ACLs to restrict device access:
{
"acls": [
{
"action": "accept",
"src": ["tag:prod"],
"dst": ["tag:sap:*"]
},
{
"action": "accept",
"src": ["tag:admin"],
"dst": ["*:*"]
}
],
"tagOwners": {
"tag:prod": ["autogroup:admin"],
"tag:sap": ["autogroup:admin"],
"tag:admin": ["autogroup:admin"]
}
}
Monitoring and Alerts
Real-time Monitoring
The TailscaleMonitor component automatically:
- Updates device status every 30 seconds
- Marks devices offline if not seen within 2 minutes
- Shows connection summary badges
- Provides manual refresh capability
Status Checks
Implement automated status checks:
// Check device status periodically
const checkConnectionStatus = async () => {
const now = new Date().toISOString();
for (const device of devices) {
if (device.status === 'active') {
const lastSeen = device.last_seen ? new Date(device.last_seen) : null;
const twoMinutesAgo = new Date(Date.now() - 2 * 60 * 1000);
if (!lastSeen || lastSeen < twoMinutesAgo) {
await supabase
.from('devices')
.update({ status: 'offline', last_seen: now })
.eq('id', device.id);
}
}
}
};
Troubleshooting
OAuth Token Errors
If you receive OAuth token errors:
- Verify Client ID and Client Secret are correct
- Check that the OAuth client has required scopes
- Ensure credentials are set in Supabase environment variables
# View Edge Function logs
supabase functions logs tailscale-api
Device Not Appearing
If a device doesn’t appear after enrollment:
- Verify auth key hasn’t expired
- Check device is running Tailscale:
- Validate device appears in Tailscale admin console
- Run sync-devices action to force synchronization
Connection Status Issues
If device status is incorrect:
- Check Realtime subscription is active
- Verify polling interval (30 seconds)
- Review last_seen timestamp in database
- Force refresh in TailscaleMonitor component