{"slug":"protect-production-postgresql-databases-from-unencrypted-macbooks","title":"Protect production PostgreSQL databases from unencrypted MacBooks","tags":["tailscale"],"agent_summary":"Last validated: Jan 13, 2026","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Protect production PostgreSQL databases from unencrypted MacBooks\r\n\r\nLast validated: Jan 13, 2026\r\n\r\nProduction database access typically requires encrypted devices, but development teams often include members whose MacBooks don't yet meet encryption requirements. Security policies force a binary choice: grant full access or deny it completely. Teams end up choosing between blocking critical work or creating security exceptions that undermine compliance.\r\n\r\nTailscale's [conditional routing](https://tailscale.com/docs/features/access-control/grants/grants-via) solves this dilemma by routing database traffic [based on device encryption status](https://tailscale.com/docs/features/device-posture). Unencrypted MacBooks don't get denied access. Their [PostgreSQL](https://www.postgresql.org/) connections go through security gateways ( [subnet routers](https://tailscale.com/docs/features/subnet-routers)) that can apply enhanced logging and controls. Encrypted devices connect directly for optimal performance, while unencrypted devices maintain connectivity through monitored paths.\r\n\r\nWhen you finish this guide, you'll have an automatic PostgreSQL routing system that maintains connectivity for all developers while applying security controls proportional to device compliance status.\r\n\r\nThe examples in this guide use a security gateway pattern for engineering teams using MacBooks to access production PostgreSQL databases. You can use this pattern to create other security gateway patterns for other teams or use cases.\r\n\r\n## [Prerequisites](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#prerequisites)\r\n\r\nBefore you begin, make sure you have:\r\n\r\n- A Tailscale account. [Create a free Personal account](https://login.tailscale.com/start) if you don't have one already.\r\n- [Admin](https://tailscale.com/docs/reference/user-roles) privileges to modify the tailnet policy file and manage device tags.\r\n- An understanding of [tailnet policy file syntax](https://tailscale.com/docs/reference/syntax/policy-file), particularly the `grants`, `postures`, and `tagOwners` sections.\r\n- At least one Linux server that can function as a [subnet router](https://tailscale.com/docs/features/subnet-routers) for your database monitoring gateway infrastructure.\r\n- Production PostgreSQL databases.\r\n- The Tailscale client is installed and running on your server. Follow the [Install Tailscale on Linux](https://tailscale.com/docs/install/linux) instructions to install the Tailscale client.\r\n- Test devices with different encryption characteristics (each with a Tailscale client installed and running):\r\n  - At least one MacBook with [FileVault](https://support.apple.com/guide/deployment/intro-to-filevault-dep82064ec40/web) encryption enabled and macOS Ventura 13.4 or later.\r\n  - At least one MacBook with FileVault encryption disabled for testing routing behavior.\r\n- (Optional) PostgreSQL client tools are installed on your test devices for connection verification.\r\n\r\n## [Step 1: Define device encryption requirements](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#step-1-define-device-encryption-requirements)\r\n\r\nThe first step is to define the device encryption requirements using [device posture policies](https://tailscale.com/docs/features/device-posture). These policies establish which MacBooks qualify for direct database access versus gateway routing by evaluating [FileVault](https://support.apple.com/guide/deployment/intro-to-filevault-dep82064ec40/web) encryption status (and other security attributes that Tailscale can detect on connected devices).\r\n\r\nDisk encryption status relies on the [mobile device management (MDM) integration](https://tailscale.com/docs/features/device-posture#edr-and-mdm-integrations) you are using:\r\n\r\n| Integration | Attribute key |\r\n| --- | --- |\r\n| [Jamf Pro](https://tailscale.com/docs/integrations/jamf-pro) | `jamfPro:fileVaultStatus` |\r\n| [SentinelOne](https://tailscale.com/docs/integrations/sentinelone) | `sentinelOne:encryptedApplications` |\r\n\r\nTo get started, open your [tailnet policy file](https://tailscale.com/docs/features/tailnet-policy-file) from the admin console. Then, locate the `postures` section in your tailnet policy file (or create it if it doesn't exist) and add the posture definition that applies to your devices:\r\n\r\nJamf Pro example:\r\n\r\n```json\r\n\"postures\": {\r\n  \"posture:encryptedMacBook\": [\\\r\n    \"node:os == 'macos'\",\\\r\n    \"node:osVersion >= '13.4.0'\",\\\r\n    \"node:tsReleaseTrack == 'stable'\",\\\r\n    \"jamfPro:fileVaultStatus == 'ALL_ENCRYPTED'\"\\\r\n  ]\r\n}\r\n```\r\n\r\nSentineOne example:\r\n\r\n```json\r\n\"postures\": {\r\n  \"posture:encryptedMacBook\": [\\\r\n    \"node:os == 'macos'\",\\\r\n    \"node:osVersion >= '13.4.0'\",\\\r\n    \"node:tsReleaseTrack == 'stable'\",\\\r\n    \"sentinelOne:encryptedApplications == true\"\\\r\n  ]\r\n}\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\nThis `encyptedMacBook` posture policy validates that devices run macOS Ventura 13.4.0 or later, use stable [Tailscale releases](https://tailscale.com/docs/install/unstable), and have FileVault disk encryption enabled. All conditions must evaluate to true for a MacBook to be compliant with this posture and qualify for direct database access. MacBooks that fail any condition in the posture definition will not match grants requiring that posture, causing them to fall through to other applicable grants that route through monitoring infrastructure.\r\n\r\nSave the policy file to apply the posture definition to your tailnet.\r\n\r\nAfter you define the encryption requirements, you can create a tag for the database monitoring gateway.\r\n\r\n## [Step 2: Create an identity for the security gateway and databases](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#step-2-create-an-identity-for-the-security-gateway-and-databases)\r\n\r\nIn this step, you'll set up identifiers for the working parts of the system, including the security gateway, the developers using MacBooks, and the databases. You'll use [tags](https://tailscale.com/docs/features/tags) for the database monitoring gateway and the databases because they're service-based. And you'll use a `group` for the developers.\r\n\r\nFirst, create the tag-based identities for the security gateway and the databases. You do this by defining `tagOwners` in the tailnet policy file. Tag owners can apply tags to devices and manage the lifecycle of tagged infrastructure.\r\n\r\nLocate the `tagOwners` section in your tailnet policy file (or create it if it doesn't exist) and define the tag for your database monitoring gateway:\r\n\r\n```json\r\n\"tagOwners\": {\r\n  \"tag:db-gateway\": [\"security-admin@yourcompany.com\"]\r\n}\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\nThen, define the tag for the databases:\r\n\r\n```json\r\n\"tagOwners\": {\r\n  \"tag:prod-database\": [\"security-admin@yourcompany.com\"]\r\n}\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\nIn this example, only the user with the email address `security-admin@yourcompany.com` can manage the `tag:db-gateway` and `tag:prod-database` tags. However, you can add multiple users, groups, or even other tags as tag owners depending on your needs.\r\n\r\nNext, use the [Tailscale CLI](https://tailscale.com/docs/reference/tailscale-cli) to assign the `tag:db-gateway` tag to the monitoring gateway server by running the following command from the monitoring gateway server:\r\n\r\n```shell\r\nsudo tailscale login --advertise-tags=tag:db-gateway\r\n```\r\n\r\nThis command assigns the `tag:db-gateway` tag to the monitoring gateway server.\r\n\r\nYou've configured the tag. Now you'll create a group for your team so you can manage permissions for your developers from a single place.\r\n\r\n## [Step 3: Create an identity for your development team](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#step-3-create-an-identity-for-your-development-team)\r\n\r\nIn this step, you'll create a group for your development team that you can use to identify the developers in your tailnet without referencing each of their email addresses.\r\n\r\nIn the tailnet policy file, create a group named `group:developers` and add the email addresses of the developers to the group. This example uses two email addresses, but you can add as many as you need.\r\n\r\n```json\r\n\"groups\": {\r\n  \"group:developers\": [\"user1@yourcompany.com\", \"user2@yourcompany.com\"]\r\n}\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\nSave the policy file to apply the group definition to your tailnet.\r\n\r\nAfter you create the group, you can configure conditional database grants.\r\n\r\n## [Step 4: Set up conditional access policies](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#step-4-set-up-conditional-access-policies)\r\n\r\nIn this step, you will configure conditional grants that route database connections based on device encryption status.\r\n\r\n[Grants](https://tailscale.com/docs/features/access-control/grants) define access control policies that determine both what database resources developers can access and how their PostgreSQL traffic reaches those resources. By combining posture requirements with the `via` field, you can create grants that route database connections based on device encryption status.\r\n\r\nFirst, locate the `grants` section in your tailnet policy file (or create it if it doesn't exist) and add the grant for encrypted MacBooks:\r\n\r\n```json\r\n\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"srcPosture\": [\"posture:encryptedMacBook\"]\\\r\n  }\\\r\n]\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\nThis grant provides direct PostgreSQL database access for development team members (`group:developers`) whose MacBooks meet the encrypted device posture requirements (`posture:encryptedMacBook`). The `srcPosture` field ensures only compliant devices match this grant, providing them with optimized routing that reduces latency and improves performance.\r\n\r\nThen, add the fallback grant after the encrypted device grant:\r\n\r\n```json\r\n\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"srcPosture\": [\"posture:encryptedMacBook\"]\\\r\n  },\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"via\": [\"tag:db-gateway\"]\\\r\n  }\\\r\n]\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\nThe second grant functions as a monitoring fallback that captures any development team PostgreSQL traffic not matched by the first grant. Because it lacks a `srcPosture` requirement, it matches devices regardless of encryption status. The [`via`](https://tailscale.com/docs/features/access-control/grants/grants-via) field routes this traffic through the device tagged as the database gateway, where you can apply additional logging and controls.\r\n\r\nSave and apply the policy changes to your tailnet.\r\n\r\nAfter you configure the grants, you can deploy the database monitoring gateway.\r\n\r\n## [Step 5: Start the security gateway](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#step-5-start-the-security-gateway)\r\n\r\nThe database monitoring gateway is a [subnet router](https://tailscale.com/docs/features/subnet-routers) that intercepts and routes PostgreSQL traffic from unencrypted MacBooks. You must configure this server as a subnet router to handle traffic forwarding and then assign the `tag:db-gateway` to enable it for routing duty. The monitoring gateway server receives all PostgreSQL traffic from unencrypted MacBooks attempting to access production databases. Consider the network positioning, performance requirements, and logging capabilities of this server when selecting hardware and deployment locations.\r\n\r\nDatabase monitoring gateways require subnet router functionality because they must forward PostgreSQL traffic between your tailnet and production database networks. Regular tailnet devices can only send and receive their own traffic. Subnet routers advertise additional network routes, enabling them to forward traffic on behalf of other devices.\r\n\r\nFirst, choose a Linux server to function as your database monitoring gateway based on your network topology and expected PostgreSQL traffic volume. This server should have sufficient network capacity and storage for comprehensive database connection logging. Then, on the selected monitoring gateway server, enable [subnet router](https://tailscale.com/docs/features/subnet-routers) functionality and assign the database gateway [tag](https://tailscale.com/docs/features/tags) by running:\r\n\r\n```shell\r\nsudo tailscale up --advertise-routes=<subnet-range> --advertise-tags=tag:db-gateway\r\n```\r\n\r\nReplace `<subnet-range>` with the actual subnet range (such as `10.0.100.0/24`) that contains your production PostgreSQL databases. This advertises the database network to your tailnet and enables the server to forward traffic to those resources.\r\n\r\nThen, approve the subnet routes in the admin console by navigating to the [Machines](https://login.tailscale.com/admin/machines) page, finding the monitoring gateway server, and enabling the advertised routes.\r\n\r\nAfter you deploy the database monitoring gateway, you can verify that the database routing behavior is working as expected by testing the connection path from an encrypted and an unencrypted MacBook.\r\n\r\n## [Step 6: Verify database routing behavior](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#step-6-verify-database-routing-behavior)\r\n\r\nWith the database monitoring gateway infrastructure deployed, when a developer's MacBook attempts to access production PostgreSQL databases, Tailscale checks device attributes against `posture:encryptedMacBook`. If the device uses encryption, the first grant matches, granting direct database access. If the device is unencrypted, the first grant fails, and the second grant matches, routing the traffic through the monitoring gateway. Let's test this behavior.\r\n\r\nFirst, identify an encrypted MacBook that meets all requirements in your `posture:encryptedMacBook` definition. Verify its compliance status by running the [`tailscale status` command](https://tailscale.com/docs/reference/tailscale-cli) directly from the MacBook:\r\n\r\n```shell\r\ntailscale status --json | grep -E \"(OS|Version|DiskEncrypted)\"\r\n```\r\n\r\nConfirm that the output shows `\"OS\": \"macos\"`, a version number of 13.4.0 or higher, and `\"DiskEncrypted\": true`.\r\n\r\nThen, check the connection path to confirm it bypasses the monitoring gateway:\r\n\r\n```shell\r\ntailscale ping <database-name>.<tailnet-name>.ts.net\r\n```\r\n\r\nReplace `<database-name>` and `<tailnet-name>` with the actual values of your production database and tailnet name.\r\n\r\nLook for direct connectivity to the production database without intermediate hops through the monitoring gateway server. The `tailscale ping` result should show a direct path to your database infrastructure.\r\n\r\nNext, from an unencrypted MacBook (one with FileVault disabled), attempt to access the same production database, then verify that PostgreSQL traffic routes through your monitoring gateway infrastructure by checking the connection path:\r\n\r\n```shell\r\ntailscale ping <database-name>.<tailnet-name>.ts.net\r\n```\r\n\r\nThe `tailscale ping` result should show connectivity through your monitoring gateway server rather than direct connectivity. This confirms that unencrypted MacBooks route through the monitoring infrastructure as intended.\r\n\r\n## [Conclusion](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#conclusion)\r\n\r\nYou've implemented device encryption-based database routing that automatically enforces security boundaries while maintaining PostgreSQL access for development teams. The system evaluates MacBook encryption status and routes traffic through appropriate network paths without manual intervention.\r\n\r\nThe final version of your tailnet policy file should look like this:\r\n\r\n```json\r\n\"postures\": {\r\n  \"posture:encryptedMacBook\": [\\\r\n    \"node:os == 'macos'\",\\\r\n    \"node:osVersion >= '13.4.0'\",\\\r\n    \"node:tsReleaseTrack == 'stable'\",\\\r\n    \"node:diskEncrypted == true\"\\\r\n  ]\r\n}\r\n\"tagOwners\": {\r\n  \"tag:db-gateway\": [\"security-admin@yourcompany.com\"],\r\n  \"tag:prod-database\": [\"security-admin@yourcompany.com\"]\r\n}\r\n\"groups\": {\r\n  \"group:developers\": [\"user1@yourcompany.com\", \"user2@yourcompany.com\"]\r\n}\r\n\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"srcPosture\": [\"posture:encryptedMacBook\"]\\\r\n  },\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"via\": [\"tag:db-gateway\"]\\\r\n  }\\\r\n]\r\n```\r\n\r\nYou can use the [visual policy editor](https://tailscale.com/docs/features/visual-editor) to manage your tailnet policy file. Refer to the [visual editor reference](https://tailscale.com/docs/reference/visual-editor) for guidance on using the visual editor.\r\n\r\n## [Further exploration](https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks\\#further-exploration)\r\n\r\nYou can expand this solution to meet your specific security requirements. For example:\r\n\r\n- Configure [logging](https://tailscale.com/docs/features/logging) on security gateways and integrate with your SIEM system for anomaly detection.\r\n- Add [just-in-time access](https://tailscale.com/docs/features/tailscale-accessbot-jit) workflows for emergency access from non-compliant devices with audit trails.\r\n- Expand posture checks to include certificates, antivirus status, or [MDM](https://tailscale.com/docs/integrations/partners/mdm) integration.\r\n- Deploy regional gateway infrastructure to reduce latency.\r\n- Create tiered access levels based on compliance levels rather than binary decisions.\r\n\r\n![Project Logo](https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed)\r\n\r\nAsk AI\r\n\r\nreCAPTCHA\r\n\r\nRecaptcha requires verification.\r\n\r\nprotected by **reCAPTCHA**\r\n","html":"<h1>Protect production PostgreSQL databases from unencrypted MacBooks</h1>\n<p>Last validated: Jan 13, 2026</p>\n<p>Production database access typically requires encrypted devices, but development teams often include members whose MacBooks don't yet meet encryption requirements. Security policies force a binary choice: grant full access or deny it completely. Teams end up choosing between blocking critical work or creating security exceptions that undermine compliance.</p>\n<p>Tailscale's <a href=\"https://tailscale.com/docs/features/access-control/grants/grants-via\">conditional routing</a> solves this dilemma by routing database traffic <a href=\"https://tailscale.com/docs/features/device-posture\">based on device encryption status</a>. Unencrypted MacBooks don't get denied access. Their <a href=\"https://www.postgresql.org/\">PostgreSQL</a> connections go through security gateways ( <a href=\"https://tailscale.com/docs/features/subnet-routers\">subnet routers</a>) that can apply enhanced logging and controls. Encrypted devices connect directly for optimal performance, while unencrypted devices maintain connectivity through monitored paths.</p>\n<p>When you finish this guide, you'll have an automatic PostgreSQL routing system that maintains connectivity for all developers while applying security controls proportional to device compliance status.</p>\n<p>The examples in this guide use a security gateway pattern for engineering teams using MacBooks to access production PostgreSQL databases. You can use this pattern to create other security gateway patterns for other teams or use cases.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#prerequisites\">Prerequisites</a></h2>\n<p>Before you begin, make sure you have:</p>\n<ul>\n<li>A Tailscale account. <a href=\"https://login.tailscale.com/start\">Create a free Personal account</a> if you don't have one already.</li>\n<li><a href=\"https://tailscale.com/docs/reference/user-roles\">Admin</a> privileges to modify the tailnet policy file and manage device tags.</li>\n<li>An understanding of <a href=\"https://tailscale.com/docs/reference/syntax/policy-file\">tailnet policy file syntax</a>, particularly the <code>grants</code>, <code>postures</code>, and <code>tagOwners</code> sections.</li>\n<li>At least one Linux server that can function as a <a href=\"https://tailscale.com/docs/features/subnet-routers\">subnet router</a> for your database monitoring gateway infrastructure.</li>\n<li>Production PostgreSQL databases.</li>\n<li>The Tailscale client is installed and running on your server. Follow the <a href=\"https://tailscale.com/docs/install/linux\">Install Tailscale on Linux</a> instructions to install the Tailscale client.</li>\n<li>Test devices with different encryption characteristics (each with a Tailscale client installed and running):\n<ul>\n<li>At least one MacBook with <a href=\"https://support.apple.com/guide/deployment/intro-to-filevault-dep82064ec40/web\">FileVault</a> encryption enabled and macOS Ventura 13.4 or later.</li>\n<li>At least one MacBook with FileVault encryption disabled for testing routing behavior.</li>\n</ul>\n</li>\n<li>(Optional) PostgreSQL client tools are installed on your test devices for connection verification.</li>\n</ul>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#step-1-define-device-encryption-requirements\">Step 1: Define device encryption requirements</a></h2>\n<p>The first step is to define the device encryption requirements using <a href=\"https://tailscale.com/docs/features/device-posture\">device posture policies</a>. These policies establish which MacBooks qualify for direct database access versus gateway routing by evaluating <a href=\"https://support.apple.com/guide/deployment/intro-to-filevault-dep82064ec40/web\">FileVault</a> encryption status (and other security attributes that Tailscale can detect on connected devices).</p>\n<p>Disk encryption status relies on the <a href=\"https://tailscale.com/docs/features/device-posture#edr-and-mdm-integrations\">mobile device management (MDM) integration</a> you are using:</p>\n<p>| Integration | Attribute key |\r\n| --- | --- |\r\n| <a href=\"https://tailscale.com/docs/integrations/jamf-pro\">Jamf Pro</a> | <code>jamfPro:fileVaultStatus</code> |\r\n| <a href=\"https://tailscale.com/docs/integrations/sentinelone\">SentinelOne</a> | <code>sentinelOne:encryptedApplications</code> |</p>\n<p>To get started, open your <a href=\"https://tailscale.com/docs/features/tailnet-policy-file\">tailnet policy file</a> from the admin console. Then, locate the <code>postures</code> section in your tailnet policy file (or create it if it doesn't exist) and add the posture definition that applies to your devices:</p>\n<p>Jamf Pro example:</p>\n<pre><code class=\"language-json\">\"postures\": {\r\n  \"posture:encryptedMacBook\": [\\\r\n    \"node:os == 'macos'\",\\\r\n    \"node:osVersion >= '13.4.0'\",\\\r\n    \"node:tsReleaseTrack == 'stable'\",\\\r\n    \"jamfPro:fileVaultStatus == 'ALL_ENCRYPTED'\"\\\r\n  ]\r\n}\n</code></pre>\n<p>SentineOne example:</p>\n<pre><code class=\"language-json\">\"postures\": {\r\n  \"posture:encryptedMacBook\": [\\\r\n    \"node:os == 'macos'\",\\\r\n    \"node:osVersion >= '13.4.0'\",\\\r\n    \"node:tsReleaseTrack == 'stable'\",\\\r\n    \"sentinelOne:encryptedApplications == true\"\\\r\n  ]\r\n}\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>This <code>encyptedMacBook</code> posture policy validates that devices run macOS Ventura 13.4.0 or later, use stable <a href=\"https://tailscale.com/docs/install/unstable\">Tailscale releases</a>, and have FileVault disk encryption enabled. All conditions must evaluate to true for a MacBook to be compliant with this posture and qualify for direct database access. MacBooks that fail any condition in the posture definition will not match grants requiring that posture, causing them to fall through to other applicable grants that route through monitoring infrastructure.</p>\n<p>Save the policy file to apply the posture definition to your tailnet.</p>\n<p>After you define the encryption requirements, you can create a tag for the database monitoring gateway.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#step-2-create-an-identity-for-the-security-gateway-and-databases\">Step 2: Create an identity for the security gateway and databases</a></h2>\n<p>In this step, you'll set up identifiers for the working parts of the system, including the security gateway, the developers using MacBooks, and the databases. You'll use <a href=\"https://tailscale.com/docs/features/tags\">tags</a> for the database monitoring gateway and the databases because they're service-based. And you'll use a <code>group</code> for the developers.</p>\n<p>First, create the tag-based identities for the security gateway and the databases. You do this by defining <code>tagOwners</code> in the tailnet policy file. Tag owners can apply tags to devices and manage the lifecycle of tagged infrastructure.</p>\n<p>Locate the <code>tagOwners</code> section in your tailnet policy file (or create it if it doesn't exist) and define the tag for your database monitoring gateway:</p>\n<pre><code class=\"language-json\">\"tagOwners\": {\r\n  \"tag:db-gateway\": [\"security-admin@yourcompany.com\"]\r\n}\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>Then, define the tag for the databases:</p>\n<pre><code class=\"language-json\">\"tagOwners\": {\r\n  \"tag:prod-database\": [\"security-admin@yourcompany.com\"]\r\n}\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>In this example, only the user with the email address <code>security-admin@yourcompany.com</code> can manage the <code>tag:db-gateway</code> and <code>tag:prod-database</code> tags. However, you can add multiple users, groups, or even other tags as tag owners depending on your needs.</p>\n<p>Next, use the <a href=\"https://tailscale.com/docs/reference/tailscale-cli\">Tailscale CLI</a> to assign the <code>tag:db-gateway</code> tag to the monitoring gateway server by running the following command from the monitoring gateway server:</p>\n<pre><code class=\"language-shell\">sudo tailscale login --advertise-tags=tag:db-gateway\n</code></pre>\n<p>This command assigns the <code>tag:db-gateway</code> tag to the monitoring gateway server.</p>\n<p>You've configured the tag. Now you'll create a group for your team so you can manage permissions for your developers from a single place.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#step-3-create-an-identity-for-your-development-team\">Step 3: Create an identity for your development team</a></h2>\n<p>In this step, you'll create a group for your development team that you can use to identify the developers in your tailnet without referencing each of their email addresses.</p>\n<p>In the tailnet policy file, create a group named <code>group:developers</code> and add the email addresses of the developers to the group. This example uses two email addresses, but you can add as many as you need.</p>\n<pre><code class=\"language-json\">\"groups\": {\r\n  \"group:developers\": [\"user1@yourcompany.com\", \"user2@yourcompany.com\"]\r\n}\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>Save the policy file to apply the group definition to your tailnet.</p>\n<p>After you create the group, you can configure conditional database grants.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#step-4-set-up-conditional-access-policies\">Step 4: Set up conditional access policies</a></h2>\n<p>In this step, you will configure conditional grants that route database connections based on device encryption status.</p>\n<p><a href=\"https://tailscale.com/docs/features/access-control/grants\">Grants</a> define access control policies that determine both what database resources developers can access and how their PostgreSQL traffic reaches those resources. By combining posture requirements with the <code>via</code> field, you can create grants that route database connections based on device encryption status.</p>\n<p>First, locate the <code>grants</code> section in your tailnet policy file (or create it if it doesn't exist) and add the grant for encrypted MacBooks:</p>\n<pre><code class=\"language-json\">\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"srcPosture\": [\"posture:encryptedMacBook\"]\\\r\n  }\\\r\n]\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>This grant provides direct PostgreSQL database access for development team members (<code>group:developers</code>) whose MacBooks meet the encrypted device posture requirements (<code>posture:encryptedMacBook</code>). The <code>srcPosture</code> field ensures only compliant devices match this grant, providing them with optimized routing that reduces latency and improves performance.</p>\n<p>Then, add the fallback grant after the encrypted device grant:</p>\n<pre><code class=\"language-json\">\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"srcPosture\": [\"posture:encryptedMacBook\"]\\\r\n  },\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"via\": [\"tag:db-gateway\"]\\\r\n  }\\\r\n]\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<p>The second grant functions as a monitoring fallback that captures any development team PostgreSQL traffic not matched by the first grant. Because it lacks a <code>srcPosture</code> requirement, it matches devices regardless of encryption status. The <a href=\"https://tailscale.com/docs/features/access-control/grants/grants-via\"><code>via</code></a> field routes this traffic through the device tagged as the database gateway, where you can apply additional logging and controls.</p>\n<p>Save and apply the policy changes to your tailnet.</p>\n<p>After you configure the grants, you can deploy the database monitoring gateway.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#step-5-start-the-security-gateway\">Step 5: Start the security gateway</a></h2>\n<p>The database monitoring gateway is a <a href=\"https://tailscale.com/docs/features/subnet-routers\">subnet router</a> that intercepts and routes PostgreSQL traffic from unencrypted MacBooks. You must configure this server as a subnet router to handle traffic forwarding and then assign the <code>tag:db-gateway</code> to enable it for routing duty. The monitoring gateway server receives all PostgreSQL traffic from unencrypted MacBooks attempting to access production databases. Consider the network positioning, performance requirements, and logging capabilities of this server when selecting hardware and deployment locations.</p>\n<p>Database monitoring gateways require subnet router functionality because they must forward PostgreSQL traffic between your tailnet and production database networks. Regular tailnet devices can only send and receive their own traffic. Subnet routers advertise additional network routes, enabling them to forward traffic on behalf of other devices.</p>\n<p>First, choose a Linux server to function as your database monitoring gateway based on your network topology and expected PostgreSQL traffic volume. This server should have sufficient network capacity and storage for comprehensive database connection logging. Then, on the selected monitoring gateway server, enable <a href=\"https://tailscale.com/docs/features/subnet-routers\">subnet router</a> functionality and assign the database gateway <a href=\"https://tailscale.com/docs/features/tags\">tag</a> by running:</p>\n<pre><code class=\"language-shell\">sudo tailscale up --advertise-routes=&#x3C;subnet-range> --advertise-tags=tag:db-gateway\n</code></pre>\n<p>Replace <code>&#x3C;subnet-range></code> with the actual subnet range (such as <code>10.0.100.0/24</code>) that contains your production PostgreSQL databases. This advertises the database network to your tailnet and enables the server to forward traffic to those resources.</p>\n<p>Then, approve the subnet routes in the admin console by navigating to the <a href=\"https://login.tailscale.com/admin/machines\">Machines</a> page, finding the monitoring gateway server, and enabling the advertised routes.</p>\n<p>After you deploy the database monitoring gateway, you can verify that the database routing behavior is working as expected by testing the connection path from an encrypted and an unencrypted MacBook.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#step-6-verify-database-routing-behavior\">Step 6: Verify database routing behavior</a></h2>\n<p>With the database monitoring gateway infrastructure deployed, when a developer's MacBook attempts to access production PostgreSQL databases, Tailscale checks device attributes against <code>posture:encryptedMacBook</code>. If the device uses encryption, the first grant matches, granting direct database access. If the device is unencrypted, the first grant fails, and the second grant matches, routing the traffic through the monitoring gateway. Let's test this behavior.</p>\n<p>First, identify an encrypted MacBook that meets all requirements in your <code>posture:encryptedMacBook</code> definition. Verify its compliance status by running the <a href=\"https://tailscale.com/docs/reference/tailscale-cli\"><code>tailscale status</code> command</a> directly from the MacBook:</p>\n<pre><code class=\"language-shell\">tailscale status --json | grep -E \"(OS|Version|DiskEncrypted)\"\n</code></pre>\n<p>Confirm that the output shows <code>\"OS\": \"macos\"</code>, a version number of 13.4.0 or higher, and <code>\"DiskEncrypted\": true</code>.</p>\n<p>Then, check the connection path to confirm it bypasses the monitoring gateway:</p>\n<pre><code class=\"language-shell\">tailscale ping &#x3C;database-name>.&#x3C;tailnet-name>.ts.net\n</code></pre>\n<p>Replace <code>&#x3C;database-name></code> and <code>&#x3C;tailnet-name></code> with the actual values of your production database and tailnet name.</p>\n<p>Look for direct connectivity to the production database without intermediate hops through the monitoring gateway server. The <code>tailscale ping</code> result should show a direct path to your database infrastructure.</p>\n<p>Next, from an unencrypted MacBook (one with FileVault disabled), attempt to access the same production database, then verify that PostgreSQL traffic routes through your monitoring gateway infrastructure by checking the connection path:</p>\n<pre><code class=\"language-shell\">tailscale ping &#x3C;database-name>.&#x3C;tailnet-name>.ts.net\n</code></pre>\n<p>The <code>tailscale ping</code> result should show connectivity through your monitoring gateway server rather than direct connectivity. This confirms that unencrypted MacBooks route through the monitoring infrastructure as intended.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#conclusion\">Conclusion</a></h2>\n<p>You've implemented device encryption-based database routing that automatically enforces security boundaries while maintaining PostgreSQL access for development teams. The system evaluates MacBook encryption status and routes traffic through appropriate network paths without manual intervention.</p>\n<p>The final version of your tailnet policy file should look like this:</p>\n<pre><code class=\"language-json\">\"postures\": {\r\n  \"posture:encryptedMacBook\": [\\\r\n    \"node:os == 'macos'\",\\\r\n    \"node:osVersion >= '13.4.0'\",\\\r\n    \"node:tsReleaseTrack == 'stable'\",\\\r\n    \"node:diskEncrypted == true\"\\\r\n  ]\r\n}\r\n\"tagOwners\": {\r\n  \"tag:db-gateway\": [\"security-admin@yourcompany.com\"],\r\n  \"tag:prod-database\": [\"security-admin@yourcompany.com\"]\r\n}\r\n\"groups\": {\r\n  \"group:developers\": [\"user1@yourcompany.com\", \"user2@yourcompany.com\"]\r\n}\r\n\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"srcPosture\": [\"posture:encryptedMacBook\"]\\\r\n  },\\\r\n  {\\\r\n    \"src\": [\"group:developers\"],\\\r\n    \"dst\": [\"tag:prod-database\"],\\\r\n    \"via\": [\"tag:db-gateway\"]\\\r\n  }\\\r\n]\n</code></pre>\n<p>You can use the <a href=\"https://tailscale.com/docs/features/visual-editor\">visual policy editor</a> to manage your tailnet policy file. Refer to the <a href=\"https://tailscale.com/docs/reference/visual-editor\">visual editor reference</a> for guidance on using the visual editor.</p>\n<h2><a href=\"https://tailscale.com/docs/solutions/protect-postgresql-unencrypted-macbooks#further-exploration\">Further exploration</a></h2>\n<p>You can expand this solution to meet your specific security requirements. For example:</p>\n<ul>\n<li>Configure <a href=\"https://tailscale.com/docs/features/logging\">logging</a> on security gateways and integrate with your SIEM system for anomaly detection.</li>\n<li>Add <a href=\"https://tailscale.com/docs/features/tailscale-accessbot-jit\">just-in-time access</a> workflows for emergency access from non-compliant devices with audit trails.</li>\n<li>Expand posture checks to include certificates, antivirus status, or <a href=\"https://tailscale.com/docs/integrations/partners/mdm\">MDM</a> integration.</li>\n<li>Deploy regional gateway infrastructure to reduce latency.</li>\n<li>Create tiered access levels based on compliance levels rather than binary decisions.</li>\n</ul>\n<p><img src=\"https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed\" alt=\"Project Logo\"></p>\n<p>Ask AI</p>\n<p>reCAPTCHA</p>\n<p>Recaptcha requires verification.</p>\n<p>protected by <strong>reCAPTCHA</strong></p>\n"}