diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,9 @@
+# Changelog for sandwich-contexts
+
+## 0.3.0.1
+
+* Automatically find sufficiently short Unix socket paths when the system temp ones are too long
+
+## 0.3.0.0
+
+* Initial release.
diff --git a/lib/Test/Sandwich/Contexts/Nix.hs b/lib/Test/Sandwich/Contexts/Nix.hs
--- a/lib/Test/Sandwich/Contexts/Nix.hs
+++ b/lib/Test/Sandwich/Contexts/Nix.hs
@@ -117,15 +117,15 @@
     , nixpkgsDerivationAllowUnfree :: Bool
     } deriving (Show, Eq)
 
--- | Nixpkgs release 24.05, accessed 6\/10\/2024.
+-- | Nixpkgs release 24.05, accessed 11\/9\/2024.
 -- You can compute updated values for this release (or others) by running
 -- nix-prefetch-github NixOS nixpkgs --rev release-24.05
 nixpkgsRelease2405 :: NixpkgsDerivation
 nixpkgsRelease2405 = NixpkgsDerivationFetchFromGitHub {
   nixpkgsDerivationOwner = "NixOS"
   , nixpkgsDerivationRepo = "nixpkgs"
-  , nixpkgsDerivationRev = "869cab745a802b693b45d193b460c9184da671f3"
-  , nixpkgsDerivationSha256 = "sha256-zliqz7ovpxYdKIK+GlWJZxifXsT9A1CHNQhLxV0G1Hc="
+  , nixpkgsDerivationRev = "bb824c634c812feede9d398c000526401028c0e7"
+  , nixpkgsDerivationSha256 = "sha256-xYnWv9kyJyF8rEZ1uJaSek2fmaIowkk/ovE6+MwcP2E="
   , nixpkgsDerivationAllowUnfree = False
   }
 
diff --git a/lib/Test/Sandwich/Contexts/PostgreSQL.hs b/lib/Test/Sandwich/Contexts/PostgreSQL.hs
--- a/lib/Test/Sandwich/Contexts/PostgreSQL.hs
+++ b/lib/Test/Sandwich/Contexts/PostgreSQL.hs
@@ -68,7 +68,8 @@
 import Test.Sandwich.Contexts.Nix
 import Test.Sandwich.Contexts.ReverseProxy.TCP
 import Test.Sandwich.Contexts.Types.Network
-import Test.Sandwich.Contexts.Util.UUID
+import Test.Sandwich.Contexts.Util.UUID (makeUUID)
+import Test.Sandwich.Contexts.UnixSocketPath
 import UnliftIO.Directory
 import UnliftIO.Environment
 import UnliftIO.Exception
@@ -213,67 +214,68 @@
   let logfileName = baseDir </> "logfile"
 
   -- The Unix socket can't live in the sandwich test tree because it has an absurdly short length
-  -- requirement (107 bytes on Linux). See
+  -- requirement (107 bytes on Linux, 104 bytes on macOS). See
   -- https://unix.stackexchange.com/questions/367008/why-is-socket-path-length-limited-to-a-hundred-chars
-  withSystemTempDirectory "postgres-nix-unix-socks" $ \unixSockDir -> do
-    bracket
-      (do
-          -- Run initdb
-          baseEnv <- getEnvironment
-          let env = ("LC_ALL", "C")
-                  : ("LC_CTYPE", "C")
-                  : baseEnv
-          withTempFile baseDir "pwfile" $ \pwfile h -> do
-            liftIO $ T.hPutStrLn h password
-            hClose h
-            createProcessWithLogging ((proc (postgresBinDir </> "initdb") [dbDirName
-                                                                            , "--username", toString username
-                                                                            , "-A", "md5"
-                                                                            , "--pwfile", pwfile
-                                                                            ]) {
-                                         cwd = Just dir
-                                         , env = Just env
-                                         })
-              >>= waitForProcess >>= (`shouldBe` ExitSuccess)
-
-          -- Turn off the TCP interface; we'll have it listen solely on a Unix socket
-          withFile (dir </> dbDirName </> "postgresql.conf") AppendMode $ \h -> liftIO $ do
-            T.hPutStr h "\n"
-            T.hPutStrLn h [i|listen_addresses=''|]
+  withUnixSocketDirectory "postgres-sock" 20 $ \unixSockDir -> bracket
+    (do
+        info [i|Unix sock dir: #{unixSockDir}|]
 
-          -- Run pg_ctl to start the DB
-          createProcessWithLogging ((proc (postgresBinDir </> "pg_ctl") [
-                                        "-D", dbDirName
-                                        , "-l", logfileName
-                                        , "-o", [i|--unix_socket_directories='#{unixSockDir}'|]
-                                        , "start" , "--wait"
-                                        ]) { cwd = Just dir })
+        -- Run initdb
+        baseEnv <- getEnvironment
+        let env = ("LC_ALL", "C")
+                : ("LC_CTYPE", "C")
+                : baseEnv
+        withTempFile baseDir "pwfile" $ \pwfile h -> do
+          liftIO $ T.hPutStrLn h password
+          hClose h
+          createProcessWithLogging ((proc (postgresBinDir </> "initdb") [dbDirName
+                                                                          , "--username", toString username
+                                                                          , "-A", "md5"
+                                                                          , "--pwfile", pwfile
+                                                                          ]) {
+                                       cwd = Just dir
+                                       , env = Just env
+                                       })
             >>= waitForProcess >>= (`shouldBe` ExitSuccess)
 
-          -- Create the default db
-          createProcessWithLogging ((proc (postgresBinDir </> "psql") [
-                                        -- "-h", unixSockDir
-                                        -- , "--username", toString postgresNixUsername
-                                        [i|postgresql://#{username}:#{password}@/?host=#{unixSockDir}|]
-                                        , "-c", [i|CREATE DATABASE #{database};|]
-                                        ]) { cwd = Just dir })
-            >>= waitForProcess >>= (`shouldBe` ExitSuccess)
+        -- Turn off the TCP interface; we'll have it listen solely on a Unix socket
+        withFile (dir </> dbDirName </> "postgresql.conf") AppendMode $ \h -> liftIO $ do
+          T.hPutStr h "\n"
+          T.hPutStrLn h [i|listen_addresses=''|]
 
+        -- Run pg_ctl to start the DB
+        createProcessWithLogging ((proc (postgresBinDir </> "pg_ctl") [
+                                      "-D", dbDirName
+                                      , "-l", logfileName
+                                      , "-o", [i|--unix_socket_directories='#{unixSockDir}'|]
+                                      , "start" , "--wait"
+                                      ]) { cwd = Just dir })
+          >>= waitForProcess >>= (`shouldBe` ExitSuccess)
 
-          files <- listDirectory unixSockDir
-          filterM ((isSocket <$>) . liftIO . getFileStatus) [unixSockDir </> f | f <- files] >>= \case
-            [f] -> pure f
-            [] -> expectationFailure [i|Couldn't find Unix socket for PostgreSQL server (check output and logfile for errors).|]
-            xs -> expectationFailure [i|Found multiple Unix sockets for PostgreSQL server, not sure which one to use: #{xs}|]
-      )
-      (\_ -> do
-          void $ readCreateProcessWithLogging ((proc (postgresBinDir </> "pg_ctl") [
-                                                   "-D", dbDirName
-                                                   , "-l", logfileName
-                                                   , "stop" , "--wait"
-                                                   ]) { cwd = Just dir }) ""
-      )
-      (\socketPath -> action socketPath)
+        -- Create the default db
+        createProcessWithLogging ((proc (postgresBinDir </> "psql") [
+                                      -- "-h", unixSockDir
+                                      -- , "--username", toString postgresNixUsername
+                                      [i|postgresql://#{username}:#{password}@/?host=#{unixSockDir}|]
+                                      , "-c", [i|CREATE DATABASE #{database};|]
+                                      ]) { cwd = Just dir })
+          >>= waitForProcess >>= (`shouldBe` ExitSuccess)
+
+
+        files <- listDirectory unixSockDir
+        filterM ((isSocket <$>) . liftIO . getFileStatus) [unixSockDir </> f | f <- files] >>= \case
+          [f] -> pure f
+          [] -> expectationFailure [i|Couldn't find Unix socket for PostgreSQL server (check output and logfile for errors).|]
+          xs -> expectationFailure [i|Found multiple Unix sockets for PostgreSQL server, not sure which one to use: #{xs}|]
+    )
+    (\_ -> do
+        void $ readCreateProcessWithLogging ((proc (postgresBinDir </> "pg_ctl") [
+                                                 "-D", dbDirName
+                                                 , "-l", logfileName
+                                                 , "stop" , "--wait"
+                                                 ]) { cwd = Just dir }) ""
+    )
+    action
 
 -- * Container
 
diff --git a/lib/Test/Sandwich/Contexts/UnixSocketPath.hs b/lib/Test/Sandwich/Contexts/UnixSocketPath.hs
new file mode 100644
--- /dev/null
+++ b/lib/Test/Sandwich/Contexts/UnixSocketPath.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE CPP #-}
+
+module Test.Sandwich.Contexts.UnixSocketPath (
+  withUnixSocketDirectory
+  , maxUnixSocketLength
+  ) where
+
+import Control.Monad.IO.Unlift
+import Relude
+import System.IO.Error (IOError)
+import Test.Sandwich.Expectations (expectationFailure)
+import UnliftIO.Directory
+import UnliftIO.Exception
+import UnliftIO.Temporary
+
+
+-- | The longest allowed path for a Unix socket on the current system.
+maxUnixSocketLength :: Int
+#ifdef mingw32_HOST_OS
+maxUnixSocketLength = maxBound
+#elif darwin_host_os
+maxUnixSocketLength = 103 -- macOS: 104 with null terminator
+#else
+maxUnixSocketLength = 107 -- Linux: 108 with null terminator
+#endif
+
+-- | Create a temporary directory in which a Unix socket can be safely created,
+-- bearing in mind the longest allowed Unix socket path on the system.
+withUnixSocketDirectory :: (MonadUnliftIO m)
+  -- | Name template, as passed to 'withSystemTempDirectory'
+  => String
+  -- | Amount of headroom to leave for a file name in this directory,
+  -- before hitting the 'maxUnixSocketLength'
+  -> Int
+  -- | Callback
+  -> (FilePath -> m a) -> m a
+withUnixSocketDirectory nameTemplate headroom action = do
+  withSystemTempDirectory nameTemplate $ \dir ->
+    if | length dir + headroom <= maxUnixSocketLength -> action dir
+       | otherwise -> withShortTempDir nameTemplate headroom action
+
+withShortTempDir :: (
+  MonadUnliftIO m
+  )
+  => String
+  -> Int
+  -> (FilePath -> m a)
+  -> m a
+withShortTempDir nameTemplate headroom action = doesDirectoryExist "/tmp" >>= \case
+  True -> isDirectoryWritable "/tmp" >>= \case
+    True -> withTempDirectory "/tmp" nameTemplate $ \dir ->
+      if | length dir + headroom <= maxUnixSocketLength -> action dir
+         | otherwise -> doFail
+    False -> doFail
+  _ -> doFail
+  where
+    doFail = expectationFailure "Couldn't create a short enough Unix socket path on this system."
+
+isDirectoryWritable :: MonadUnliftIO m => FilePath -> m Bool
+isDirectoryWritable dir = do
+  try (getPermissions dir) >>= \case
+    Left (_ :: IOError) -> return False
+    Right perms -> return $ writable perms
diff --git a/lib/Test/Sandwich/Contexts/Util/SocketUtil.hs b/lib/Test/Sandwich/Contexts/Util/SocketUtil.hs
deleted file mode 100644
--- a/lib/Test/Sandwich/Contexts/Util/SocketUtil.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-module Test.Sandwich.Contexts.Util.SocketUtil (
-  isPortOpen
-  , simpleSockAddr
-  ) where
-
--- Taken from
--- https://stackoverflow.com/questions/39139787/i-want-to-check-whether-or-not-a-certain-port-is-open-haskell
--- https://gist.github.com/nh2/0a1442eb71ec0405a1e3ce83a467dfde#file-socketutils-hs
-
-import Foreign.C.Error (Errno(..), eCONNREFUSED)
-import GHC.IO.Exception (IOException(..))
-import Network.Socket (Family(AF_INET), PortNumber, SocketType(Stream), SockAddr(SockAddrInet), socket, connect, close', tupleToHostAddress)
-import Relude
-import UnliftIO.Exception
-
--- | Checks whether @connect()@ to a given TCPv4 `SockAddr` succeeds or
--- returns `eCONNREFUSED`.
---
--- Rethrows connection exceptions in all other cases (e.g. when the host
--- is unroutable).
-isPortOpen :: SockAddr -> IO Bool
-isPortOpen sockAddr = do
-  bracket (socket AF_INET Stream 6 {- TCP -}) close' $ \sock -> do
-    res <- try $ connect sock sockAddr
-    case res of
-      Right () -> return True
-      Left e ->
-        if (Errno <$> ioe_errno e) == Just eCONNREFUSED
-          then return False
-          else throwIO e
-
-
--- | Creates a `SockAttr` from host IP and port number.
---
--- Example:
--- > simpleSockAddr (127,0,0,1) 8000
-simpleSockAddr :: (Word8, Word8, Word8, Word8) -> PortNumber -> SockAddr
-simpleSockAddr addr port = SockAddrInet port (tupleToHostAddress addr)
-
-
--- Example usage:
--- > isPortOpen (simpleSockAddr (127,0,0,1) 8000)
--- True
diff --git a/sandwich-contexts.cabal b/sandwich-contexts.cabal
--- a/sandwich-contexts.cabal
+++ b/sandwich-contexts.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           sandwich-contexts
-version:        0.3.0.0
+version:        0.3.0.1
 synopsis:       Contexts for the Sandwich test library
 description:    Please see the <https://codedownio.github.io/sandwich documentation>.
 author:         Tom McLaughlin
@@ -13,6 +13,8 @@
 copyright:      2024 Tom McLaughlin
 license:        BSD3
 build-type:     Simple
+extra-source-files:
+    CHANGELOG.md
 
 library
   exposed-modules:
@@ -29,9 +31,9 @@
       Test.Sandwich.Contexts.FakeSmtpServer.Derivation
       Test.Sandwich.Contexts.Files.Types
       Test.Sandwich.Contexts.ReverseProxy.TCP
+      Test.Sandwich.Contexts.UnixSocketPath
       Test.Sandwich.Contexts.Util.Aeson
       Test.Sandwich.Contexts.Util.Nix
-      Test.Sandwich.Contexts.Util.SocketUtil
       Test.Sandwich.Contexts.Util.UUID
       Paths_sandwich_contexts
   hs-source-dirs:
