{"id":10545,"date":"2025-05-06T06:05:27","date_gmt":"2025-05-06T10:05:27","guid":{"rendered":"https:\/\/www.both.org\/?p=10545"},"modified":"2025-05-06T06:05:27","modified_gmt":"2025-05-06T10:05:27","slug":"standard-unix-password-manager","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=10545","title":{"rendered":"Standard UNIX password manager"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"10545\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p>The <code>pass<\/code> command is a password manager that uses GPG encryption to keep your passwords safe, and it features several system integrations so you can use it seamlessly with your web browser of choice.<\/p>\n\n\n\n<p>Password management is one of those computing problems you probably don&#8217;t think about often, because modern computing usually has an obvious default solution built-in. A website prompts you for a password, and your browser auto-fills it in for you. Problem solved. However, not all browsers make it very easy to get to your passwords store, which makes it complex to migrate passwords to a new system without also migrating the rest of your user profile, or to share certain passwords between different users. There are several good open source options that offer alternatives to the obvious defaults, but as a user of Linux and UNIX, I love a minimal and stable solution when one is available.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install pass<\/h2>\n\n\n\n<p>The <code>pass<\/code> command is provided by the <a href=\"https:\/\/www.passwordstore.org\">PasswordStore<\/a> project. You can install it from your software repository or ports collection. For example, on Fedora:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo dnf install pass<\/code><\/pre>\n\n\n\n<p>On Debian and similar:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo apt install pass<\/code><\/pre>\n\n\n\n<p>Because the word <code>pass<\/code> is common, the name of the package may vary, depending on your distribution and operating system. For example, <code>pass<\/code> is available on Slackware and FreeBSD as <code>password-store<\/code>.<\/p>\n\n\n\n<p>The <code>pass<\/code> command is open source, so the source code is available at <a href=\"https:\/\/git.zx2c4.com\/password-store\">git.zx2c4.com\/password-store<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create a GPG key<\/h2>\n\n\n\n<p>First, you must have a GPG key to use for encryption. You can use a key you already have, or create a new one just for your password store.<\/p>\n\n\n\n<p>To create a GPG key, use the <code>gpg<\/code> command along with the <code>--gen-key<\/code> option (if you already have a key you want to use for your password store, you can skip this step):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gpg --gen-key<\/code><\/pre>\n\n\n\n<p>Answer the prompts to generate a key. When prompted to provide values for <strong>Real name<\/strong>, <strong>Email<\/strong>, and <strong>Comment<\/strong>, you must provide a response for each one, even though GPG allows you to leave them empty. In my experience, <code>pass<\/code> fails to initialize when one of those values is empty. For example, here are my responses for purposes of this article:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Real name: Tux\nEmail: tux@example.com\nComment: My first key<\/code><\/pre>\n\n\n\n<p>This information is combined, in a different order, to create a unique GPG ID. You can see your GPG key ID at any time:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gpg --list-secret-keys | grep uid\nuid:      Tux (My first key) tux@example.com<\/code><\/pre>\n\n\n\n<p>Other than that, it&#8217;s safe to accept the default and recommended options for each prompt.<\/p>\n\n\n\n<p>In the end, you have a GPG key to serve as the master key for your password store. You must keep this key safe. Back it up, keep a copy of your GPG keyring on a secure device. Should you lose this key, you lose access to your password store.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Initialize a password store<\/h2>\n\n\n\n<p>Next, you must initialize a password store on your system. When you do, you create a hidden directory where your passwords are stored, and you define which GPG key to use to encrypt passwords. To initialize a password store, use the <code>pass init<\/code> command along with your unique GPG key ID. Using my example key:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ pass init \"Tux (My first key) &lt;tux@example.com&gt;\"<\/code><\/pre>\n\n\n\n<p>You can define more than one GPG key to use with your password store, should you intend to share passwords with another user or on another system using a different GPG key.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Add and edit passwords<\/h2>\n\n\n\n<p>To add a password to your password store, use the <code>pass insert<\/code> command followed by the URL (or any string) you want <code>pass<\/code> to keep.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ pass insert example.org<\/code><\/pre>\n\n\n\n<p>Enter the password at the prompt, and then again to confirm.<\/p>\n\n\n\n<p>Most websites require more than just a password, and so <code>pass<\/code> can manage additional data, like username, email, and any other field. To add extra data to a password file, use <code>pass edit<\/code> followed by the URL or string you saved the password as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ pass edit example.org<\/code><\/pre>\n\n\n\n<p>The first line of a password file must be the password itself. After that first line, however, you can add any additional data you want, in the format of the field name followed by a colon and then the value. For example, to save <code>tux<\/code> as the value of the <code>username<\/code> field on a website:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myFakePassword123\nusername: tux<\/code><\/pre>\n\n\n\n<p>Some websites use an email address instead of a username:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myFakePassword123\nemail: tux@example.com<\/code><\/pre>\n\n\n\n<p>A password file can contain any data you want, so you can also add important notes or one-time recovery codes, and anything else you might find useful:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myFake;_;Password123\nemail: tux@example.com\nrecovery email: tux@example.org\nrecovery code: 03a5-1992-ee12-238c\nnote: This is your personal account, use company SSO at work<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">List passwords<\/h2>\n\n\n\n<p>To see all passwords in your password store:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ pass list\nPassword Store\n\u251c\u2500\u2500 example.com\n\u251c\u2500\u2500 example.org<\/code><\/pre>\n\n\n\n<p>You can also search your password store:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ pass find bandcamp\nSearch Terms: bandcamp\n\u2514\u2500\u2500 www.bandcamp.com<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Integrating your password store<\/h2>\n\n\n\n<p>Your password store is perfectly usable from a terminal, but that&#8217;s not the only way to use it. Using extensions, you can use <code>pass<\/code> as your web browser&#8217;s password manager.<\/p>\n\n\n\n<p>There are several different applications that provide a bridge between <code>pass<\/code> and your browser. Most are listed in the <strong>CompatibleClients<\/strong> section of <a href=\"https:\/\/www.passwordstore.org\">passwordstore.org<\/a>.<\/p>\n\n\n\n<p>I use <a href=\"https:\/\/codeberg.org\/PassFF\/passff-host\">PassFF<\/a>, which provides a <a href=\"https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/passff\/\">Firefox extension<\/a>. For browsers based on Chromium, you can use <a href=\"https:\/\/github.com\/browserpass\/browserpass-native\">Browserpass<\/a> with the <a href=\"https:\/\/github.com\/browserpass\/browserpass-extension\">Browserpass extension<\/a>.<\/p>\n\n\n\n<p>In both cases, the browser extension requires a &#8220;host application&#8221;, or a background bridge service to allow your browser to access the encrypted data in your password store.<\/p>\n\n\n\n<p>For PassFF, download the install script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ wget https:\/\/codeberg.org\/PassFF\/passff-host\/releases\/download\/latest\/install_host_app.sh<\/code><\/pre>\n\n\n\n<p>Review the script to confirm that it&#8217;s just installing the host application, and then run it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ bash .\/install_host_app.sh firefox\nPython 3 executable located at \/usr\/bin\/python3\nPass executable located at \/usr\/bin\/pass\nInstalling Firefox host config\nNative messaging host for Firefox has been installed to \/home\/tux\/.mozilla\/native-messaging-hosts.<\/code><\/pre>\n\n\n\n<p>Install the browser extension, and then restart your browser. When you navigate to a URL with an file in your password store, a <code>pass<\/code> icon appears in the relevant fields. Click the icon to complete the form.<\/p>\n\n\n\n<p>Alternately, a <code>pass<\/code> icon appears in your browser&#8217;s extension tray, providing a menu for direct interaction with many <code>pass<\/code> functions (such as copying data directly to your system clipboard, or auto-filling only a specific field, and so on.)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Password management like UNIX<\/h2>\n\n\n\n<p>The <code>pass<\/code> command is extensible, and there are some great add-ons for it. Here are some of my favourites:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/tadfisher\/pass-otp#readme\">pass-otp<\/a>: Add one-time password (OTP) functionality.<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/roddhjav\/pass-update#readme\">pass-update<\/a>: Add an easy workflow for updating passwords that you frequently change.<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/roddhjav\/pass-import#readme\">pass-import<\/a>: Import passwords from chrome, 1password, bitwarden, apple-keychain, gnome-keyring, keepass, lastpass, and many more (including <code>pass<\/code> itself, in the event you want to migrate a password store).<\/li>\n<\/ul>\n\n\n\n<p>The <code>pass<\/code> command and the password store system is a comfortably UNIX-like password management solution. It stores your passwords as text files in a format that doesn&#8217;t even require you to have <code>pass<\/code> installed for access. As long as you have your GPG key, you can access and use the data in your password store. You own your data not only in the sense that it&#8217;s local, but you have ownership of how you interact with it. You can sync your password stores between different machines using rsync or syncthing, or even backup the store to cloud storage. It&#8217;s encrypted, and only you have the key.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The pass command is a password manager that uses GPG encryption to keep your passwords safe, and it<\/p>\n","protected":false},"author":31,"featured_media":10546,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[75,178],"tags":[],"class_list":["post-10545","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","category-tools"],"modified_by":"David Both","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10545","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10545"}],"version-history":[{"count":2,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10545\/revisions"}],"predecessor-version":[{"id":10548,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10545\/revisions\/10548"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/10546"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}