diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Changelog for `password-persistent`
+
+## 0.1.0.0
+
+- Split from `password-instances`.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) Dennis Gosnell, 2019; Felix Paulusma, 2020
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Dennis Gosnell, Felix Paulusma nor the names
+      of other contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,11 @@
+# password-persistent
+
+[![Build Status](https://github.com/cdepillabout/password/workflows/password/badge.svg)](http://github.com/cdepillabout/password)
+[![Hackage](https://img.shields.io/hackage/v/password-persistent.svg)](https://hackage.haskell.org/package/password-persistent)
+[![Stackage LTS](http://stackage.org/package/password-persistent/badge/lts)](http://stackage.org/lts/package/password-persistent)
+[![Stackage Nightly](http://stackage.org/package/password-persistent/badge/nightly)](http://stackage.org/nightly/package/password-persistent)
+[![BSD3 license](https://img.shields.io/badge/license-BSD3-blue.svg)](./LICENSE)
+
+This package provides `persistent` typeclass instances for the plain-text password
+and hashed password datatypes from the
+[password](https://hackage.haskell.org/package/password) package.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -Wall #-}
+module Main (main) where
+
+#ifndef MIN_VERSION_cabal_doctest
+#define MIN_VERSION_cabal_doctest(x,y,z) 0
+#endif
+
+#if MIN_VERSION_cabal_doctest(1,0,0)
+
+import Distribution.Extra.Doctest ( defaultMainWithDoctests )
+main :: IO ()
+main = defaultMainWithDoctests "doctests"
+
+#else
+
+#ifdef MIN_VERSION_Cabal
+-- If the macro is defined, we have new cabal-install,
+-- but for some reason we don't have cabal-doctest in package-db
+--
+-- Probably we are running cabal sdist, when otherwise using new-build
+-- workflow
+#warning You are configuring this package without cabal-doctest installed. \
+         The doctests test-suite will not work as a result. \
+         To fix this, install cabal-doctest before configuring.
+#endif
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
+
+#endif
diff --git a/password-persistent.cabal b/password-persistent.cabal
new file mode 100644
--- /dev/null
+++ b/password-persistent.cabal
@@ -0,0 +1,83 @@
+cabal-version: 1.12
+
+name:           password-persistent
+version:        0.1.0.0
+category:       Security
+synopsis:       persistent typeclass instances for password package
+description:    A library providing typeclass instances for `persistent` for the types from the password package.
+homepage:       https://github.com/cdepillabout/password/tree/master/password-persistent#readme
+bug-reports:    https://github.com/cdepillabout/password/issues
+author:         Dennis Gosnell, Felix Paulusma
+maintainer:     cdep.illabout@gmail.com, felix.paulusma@gmail.com
+copyright:      Copyright (c) Dennis Gosnell, 2019; Felix Paulusma, 2020
+license:        BSD3
+license-file:   LICENSE
+build-type:     Custom
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://github.com/cdepillabout/password
+
+custom-setup
+  setup-depends:
+      base           >= 4.9   && < 5
+    , Cabal                      < 4
+    , cabal-doctest  >= 1.0.6 && < 1.1
+
+library
+  hs-source-dirs:
+      src
+  exposed-modules:
+      Data.Password.Persistent
+--   other-modules:
+--       Paths_password_persistent
+  build-depends:
+      base          >= 4.9 && < 5
+    , password-types          < 2
+    , persistent    >= 1.2 && < 3
+    , text                    < 3
+  ghc-options:
+      -Wall
+  default-language:
+      Haskell2010
+
+test-suite doctests
+  type:
+      exitcode-stdio-1.0
+  hs-source-dirs:
+      test/doctest
+  main-is:
+      doctest.hs
+  ghc-options:
+      -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >= 4.9 && < 5
+    , base-compat
+    , doctest
+    , password
+  default-language:
+      Haskell2010
+
+test-suite password-persistent-tasty
+  type:
+      exitcode-stdio-1.0
+  hs-source-dirs:
+      test/tasty
+  main-is:
+      Spec.hs
+  ghc-options:
+      -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >= 4.9 && < 5
+    , password-persistent
+    , password-types
+    , persistent
+    , quickcheck-instances
+    , tasty
+    -- , tasty-hunit
+    , tasty-quickcheck
+  default-language:
+      Haskell2010
diff --git a/src/Data/Password/Persistent.hs b/src/Data/Password/Persistent.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Password/Persistent.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+{-|
+Module      : Data.Password.Persistent
+Copyright   : (c) Dennis Gosnell, 2019; Felix Paulusma, 2020
+License     : BSD-style (see LICENSE file)
+Maintainer  : cdep.illabout@gmail.com
+Stability   : experimental
+Portability : POSIX
+
+This module provides `persistent` typeclass instances
+for 'Password' and 'PasswordHash'.
+
+See the "Data.Password.Types" module for more information.
+-}
+
+module Data.Password.Persistent () where
+
+import Data.Password.Types
+#if !MIN_VERSION_base(4,13,0)
+import Data.Semigroup ((<>))
+#endif
+import Data.Text (pack)
+import Data.Text.Encoding as TE (decodeUtf8')
+import Database.Persist (PersistValue(..))
+import Database.Persist.Class (PersistField(..))
+import Database.Persist.Sql (PersistFieldSql(..))
+import GHC.TypeLits (TypeError, ErrorMessage(..))
+
+-- $setup
+-- >>> :set -XOverloadedStrings
+-- >>> :set -XDataKinds
+--
+-- Import needed functions.
+--
+-- >>> import Data.Password.Bcrypt (Salt(..), hashPasswordWithSalt, unsafeShowPassword)
+-- >>> import Data.Password.Types (mkPassword)
+-- >>> import Database.Persist.Class (PersistField(toPersistValue))
+
+type ErrMsg = 'Text "Warning! Tried to convert plain-text Password to PersistValue!"
+         :$$: 'Text "  This is likely a security leak. Please make sure whether this was intended."
+         :$$: 'Text "  If this is intended, please use 'unsafeShowPassword' before converting to PersistValue."
+         :$$: 'Text ""
+
+-- | This instance allows a 'PasswordHash' to be stored as a field in a database using
+-- "Database.Persist".
+--
+-- >>> let salt = Salt "abcdefghijklmnop"
+-- >>> let pass = mkPassword "foobar"
+-- >>> let hashedPassword = hashPasswordWithSalt 10 salt pass
+-- >>> toPersistValue hashedPassword
+-- PersistText "$2b$10$WUHhXETkX0fnYkrqZU3ta.N8Utt4U77kW4RVbchzgvBvBBEEdCD/u"
+--
+-- In the example above, the long 'PersistText' will be the value you store in
+-- the database.
+--
+-- We don't provide an instance of 'PersistField' for 'Password', because we don't
+-- want to make it easy to store a plain-text password in the database.
+instance PersistField (PasswordHash a) where
+  toPersistValue (PasswordHash hpw) = PersistText hpw
+  fromPersistValue = \case
+      PersistText txt -> Right $ PasswordHash txt
+      PersistByteString bs ->
+        either failed (Right . PasswordHash) $ TE.decodeUtf8' bs
+      _ -> Left "could not parse PasswordHash from PersistValue"
+    where
+      failed e = Left $ "Failed decoding PasswordHash to UTF8: " <> pack (show e)
+
+-- | This instance allows a 'PasswordHash' to be stored as a field in an SQL
+-- database in "Database.Persist.Sql".
+deriving newtype instance PersistFieldSql (PasswordHash a)
+
+-- | Type error! Do not store plain-text 'Password's in your database!
+instance TypeError ErrMsg => PersistField Password where
+  toPersistValue = error "unreachable"
+  fromPersistValue = error "unreachable"
diff --git a/test/doctest/doctest.hs b/test/doctest/doctest.hs
new file mode 100644
--- /dev/null
+++ b/test/doctest/doctest.hs
@@ -0,0 +1,14 @@
+module Main where
+
+import Build_doctests (flags, pkgs, module_sources)
+-- import Data.Foldable (traverse_)
+import System.Environment.Compat (unsetEnv)
+import Test.DocTest (doctest)
+
+main :: IO ()
+main = do
+  -- traverse_ putStrLn args
+  unsetEnv "GHC_ENVIRONMENT"
+  doctest args
+  where
+    args = flags ++ pkgs ++ module_sources
diff --git a/test/tasty/Spec.hs b/test/tasty/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/tasty/Spec.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+import Database.Persist.Class (PersistField (..))
+import Test.Tasty (TestTree, defaultMain, testGroup)
+import Test.Tasty.QuickCheck (testProperty, (===))
+import Test.QuickCheck.Instances.Text ()
+
+import Data.Password.Types (PasswordHash (..))
+import Data.Password.Persistent()
+
+
+main :: IO ()
+main = defaultMain $ testGroup "Password Instances"
+  [ persistTest
+  ]
+
+persistTest :: TestTree
+persistTest = testProperty "PasswordHash (PersistField)" $ \pass ->
+    let pwd = PasswordHash pass
+    in fromPersistValue (toPersistValue pwd) === Right pwd
