Dotenv plugin does not work with private plugin

Hello everyone,

I have a Grav site where a page which can only be accessed with a password. I made this with the private plugin. For security purposes, I would rather not store the password in /user/config/plugins/private.yaml.

Since I use the dotenv plugin for the email-sendgrid API key (I get it from Dopper, a secrets manager), I thought I could do it here too. But regardless of what I try, I get this error:

my .gravenv file looks live this:


Does anyone have a similar issue or an idea what the issue is causing & how to resolve it?

What I have already tried/ checked:

  • if the problem is caused by the _ in no_user:
    ⇒ no, it works with api_key too
  • if the problem is caused by the nested config users.no_user:
    ⇒ no, it works in too
  • comment/ uncomment the user.no_user line in private.yaml:
    ⇒ doesn’t matter

First, thank you for describing your problem and what you’ve tried, so well and so respectfully! I’m sorry I can’t help with a solution. If I had time, I might set up a test and try to reproduce it. If you get no responses, I think it will just be because no-one has a solution or suggestion.

I have never noticed these plugins though they are in the official repos. However, Private was replaced by Private Site which I have seen before (never tried, AFAIR). Both private plugins are pretty old! I’m not surprised there are issues.

So I have a few more comments about your choice of plugins. Can’t you achieve what Private Site does just using groups and the Login plugin? I’d have more confidence in that being supported in future.

Also I don’t see the benefit of Dotenv at all. I use config and user/env to store all of my config variations. Perhaps it’s slightly simpler to edit every change in one place, but how is a secret being in a dotfile more secure? It’s hidden from standard listings but that’s not security, that’s (weak) obscurity. What am I missing about its benefit?

This is off topic slightly, so don’t feel obligated to answer promptly if you are short of time. Thank you for bringing these plugins to my attention.

1 Like

Thanks for your response @hughbris!

Unfortunately, no, I can’t. It’s a website for a client, a small society which need a password protected page on the website for their members, so they can access it with a shared password.

I develop this and other websites with git, and upload the code to GitHub. Since I don’t want any passwords, keys and other secrets hard-coded, I use Doppler, a secrets manager, to manage them.
When I deploy the website, I have a script which gets the secrets from Doppler and stores them temporary in a dotenv file, since that’s the only way I can achieve using secrets like that with Grav.

I have already tried various other tools and methods, but for me, that’s the simplest and most secure way. If you use another method or have an idea what would work, I’m open for new stuff.

1 Like

Somehow I’m unable to edit the post again, so here are some edits in form of a reply:

Pastebin of error screen:

  • The error somehow occurs only with the dotenv + private plugin.
    ⇒ With other tested plugins, I get no error message at all
  • I get the same error with every config field I tried with the private plugin.
    ⇒ It seems to be an error with the whole plugin, since even text fields don’t work

@chraebsli, Instead of trying to solve the issue on a very, very old plugin which is also no longer supported, I would rather try to implement the suggestion from @hughbris: Using the standard Grav way to secure pages.

Ask yourself:

  • “What are the risks/damages if the password is exposed?”
  • “Is the risk/damage high enough to spent more time and money going beyond the security that Grav provides?”.

Using Grav’s solution:

  • You can use a single dummy account and share the username/password with the members.
  • The plain password is stored nowhere.
    The password of the account will be stored as a hash in the accounts file.
  • Hashing is a one-way process.
    • When a user logs in, the password entered in the login form will be hashed and compared with the stored hash in the account.
    • If exposed, the hash is just a bunch of characters.
    • Only by guessing the password (or brute force trial and error) might the password be discovered.
  • Add the accounts folder to .gitignore to prevent publishing on Github.
  • You can easily replace the password of the dummy account using the CLI of the Login plugin.

My two cents…


Thanks @anon76427325, I just tested it and got it working in like 2 minutes!

I didn’t know about this built-in feature of Grav, but I’m glad you brought it to me. I guess there isn’t an easy way that the user doesn’t have to enter a username, but I think my client will be ok with that.

Have a nice day everyone!

@chraebsli, Nice!

Please know the forum is a two-way street…

For the benefit of the community, it would be nice if you could share the steps (+ code snippets, frontmatter, etc. if relevant) you’ve taken to implement the private page. If you just followed the docs, you may share the link.

How I resolved the problem:

  1. Create a new account with access on site.login = true
  2. In admin, update the “Page Access” configuration in the security tab of the page to this:
  3. This relates to these lines of code in the frontmatter of the page:
    visibility_requires_access: true
    site.login: true

I’m glad you solved this. Just want to address a couple of points you made in reply to my original comment.

I’m curious what you thought I meant. I probably didn’t explain it very well but @anon76427325 seems to have got through with a better explanation.

I think Git is the only sane way to manage and escalate. I use private repos but also do what I can to leave secrets out of my repos.

I employ a technique where I store as much config as possible globally and try to keep configs containing secrets to environment configs. That allows me to commit most of my configuration. I upload the environment configs containing secrets with scp, keeping a list of those. I will shortly “upgrade” that system to rsync. Would love a better system to manage that.

For example, user/config/form.yaml: (committed)

    theme: dark
    # NOTE - refer configs under env for site_key & secret_key

env/prod/config/plugins/form.yaml: (git ignores this)

    site_key: SITE_KEY_HERE
    secret_key: SECRET_KEY_HERE

I don’t particularly like having secrets in the filesystem at all either, especially in plain text as most plugins do. Some plugins support environment variables but that seems like more overhead for questionable benefit. Because Docker Compose files run everything, I’d need to pass them in there and then delete the compose file. That would fall over very time the container restarts unattended.

I somewhat mitigate exposure by restricting the scope of what credentials can do, which is a little more setup. That is, avoiding reusing credentials as much as possible (across sites and environments). I could probably more actively monitor abuse too (e.g. alerts for spikes in API usage).

Every CMS and framework I have used stores secrets somewhere on the file system. It doesn’t sit well with me but I can’t recall an attack based on that.

I know this is solved, I just enjoy talking about it and sharing solutions :slight_smile:

Thanks for your explanation of how you do it. Since I’m a young dev, I’m very glad more experienced devs like you and others give feedback and share their knowledge and practices!

I thought you meant access to the page within the admin panel. I just needed a more detailed explanation because I didn’t know this was possible.

Thanks for sharing. I will try your approach on the next project I do. But could you please provide me some more information of how this is more secure? For me, it looks like it’s the same approach as mine, just that you have the file with the secrets somewhere else.
And isn’t it a bit less secure and more complicated when you have to manually copy the secrets to the server via scp when I use a secrets manager with a script to get them to the config?

I don’t mean to offend you, I just want to understand your perspective and learn new, more secure and more common practices.

I didn’t mean to imply it’s more secure. It’s simply easier to manage for me and it allows me to commit more of the configuration settings, which I like.

There are whole DevOps systems to automate all of this (e.g. Ansible). I like the idea, I’m working towards automating as much as possible, but every one of those solutions seems overengineered to me. The ubiquity of the YAML format mixing declarative and imperative paradigms turns me off a lot.

None taken. Good for you, pick away :smiley:

Far down on my todo list is to document and share my workflow and boilerplate Grav configurations. Still looking around for a good tool/platform for that too.

The first time I worked with Grav I committed literally EVERYTHING. Empty .gitignore. Then I learned how GPM and other stuff works and I committed less but still too much. And with every project, I am learning new stuff and get more efficient with what I commit.
Just a few weeks ago, I forked Grav to build a template, so I can fork this for any new project, so I don’t have to start from “scratch” with a new Grav system. Also, I think I can update older projects better with this.

⇒ What I want to say with this is that even when you think you know everything and are 100% efficient, you are not. I know you have definitely much more experience with Grav and you have your workflows which you use every time, but you can still explore new and more efficient practices.

⇒ I’m sure scp works best for you since you probably used it for many years. And I totally agree with you that many DevOps systems have too many features and are too complicated for most use cases.
But since I know Doppler, I can’t work without it, no matter if I use Grav or Node.js. For me, it’s very simple to use, and it has a good CLI. I only use the free version, but I can do everything I need: manage secrets and use them.
Give it a try, it’s worth it!

Use GitHub, it’s the most famous one and the first source most people search for such stuff.

  • Share your starting point repo if you have one, otherwise create one.
    • Share your plugins, themes, skeletons
    • Use GitHub Gists for code snippets
  • Host a Grav blog site where you share your knowledge and practices.

Just put it anywhere on the internet where people search for.