a Python script for secret management

Karam Assany 8f70d62b28 Fixed a few things 2 months ago
LICENSE 55bd592d3f Initial commit 3 months ago
README.md 8f70d62b28 Fixed a few things 2 months ago
secs.py 8f70d62b28 Fixed a few things 2 months ago



secs is a minimalist Python script for secret management. It utilizes GnuPG to symmetrically encrypt and decrypt the secret database, the rest is done by Python and its internal modules. So yeah, zero need for external dependencies (aside from GnuPG). It's just a script after all.


Please note that secs is only tested on GNU/Linux. It should work on other platforms but no guarantees :)


  • GnuPG (available in the path as gpg)
  • Python 3.5 or later

Download secs.py:

# Git clone
git clone --depth 1 https://notabug.org/karam/secs

# install it only for your user
install secs/secs.py ~/.local/bin/secs
# or system-wide
sudo install secs/secs.py /usr/local/bin/secs

If your preferred Python executable does not exist at /usr/bin/env python3, then remember to edit the shebang line accordingly.


The secret database is technically a Python dictionary encoded in a text file that is symmetrically encrypted by gpg. Secrets can be referred to by their tags, so one tag can point to one secret at one time. It's preferable for tags to consist only of alphabetical and numeral characters (and underscores _); just to make them easy to pass as command line arguments.


secs requires an environment variable SECS_DB that points to the absolute path of the secret database. You can create a blank database by issuing mkdatabase:

SECS_DB=/path/to/database secs mkdatabase

Instead of passing SECS_DB every time, append it to your login .profile (or .bash_profile, .zprofile, etc depending on your shell):

echo 'export SECS_DB=/path/to/database' >> ~/.profile


To get a brief help message, pass nothing


To add new secrets

secs add TAG1 [TAG2 ...]

To get existing secrets

secs get TAG1 [TAG2 ...]

To change existing secrets

secs set TAG1 [TAG2 ...]

To delete existing secrets

secs del TAG1 [TAG2 ...]

To create a new secret database (nothing should exist at the SECS_DB path)

secs mkdatabase

To list all tags or tags matching the given REGEX

secs ls [REGEX]

To change the passphrase of the database

secs passwd


To make things clear:

  • Database path is passed as an environment variable.
  • Passphrases are passed from silent input.
  • Commands, tags and regexes are passed as command line arguments.
  • Secrets are passed from and to standard I/O.

Incremental backups

Whenever a change occurs on the database, a backup in the same directory of the database will be beforely created. Backups are suffixed with their creation timestamp, so they will never get overwritten. This behavior is the default, you can disable it by passing a SECS_NOBACKUPS environment variable (no matter what it contains). If disabled, an old backup will be overwritten with a new one.


Because of the *UNIX*ish way that secs handles I/O, you can always combine it with other programs or even secs itself.


secs get $(secs ls vpn)
secs del $(secs ls) # warning: this cleans your database

(Unfortunately, secs will ask you for the passphrase twice)

To "rename" a secret (change its tag):

secs get old_tag > tmp && secs add new_tag < tmp && secs del old_tag
rm tmp # make sure 'tmp' is deleted

(in theory, we could pipe secs get and secs add together, but unfortnately it didn't work for me)

If you have a solution for the type-passphrase-for-each-command problem, and the pipeline problem (maybe implementing a lock-and-unlock mechanism?), then please help me to get it done.


secs is licensed under the MIT (Expat) license.

Copyright (C) 2020 Karam Assany (karam.assany@tuta.io)