Keeping API keys secret (on Github) using a .env file


Apologies if this has been asked before, but I’m new to Hugo, and I thought the best way to understand it would be to build a new theme.

My code is on a public repository in Github, and I’d like to keep it as a publicly available resource.

I am trying to add a Google reCAPTCHA to my contact form. I’m trying to follow this post.

The reCAPTCHA has a secret key that I would like to keep private.

I have set up a .env file in the project’s root directory on my local machine, and I have edited the gitignore file to exclude files ending in ‘.env’ from git.

  1. What is the syntax to define a variable in the .env file? Is the syntax similar to defining a params variable in config.toml ie.

gtm = “google tag manager id”

  1. How do I pass this variable into a template page?

I have tried

{{ $gtm := getenv “HUGO_gtm” }}

{{ $gtm }}


{{ $gtm := getenv “gtm” }}

{{ $gtm }}

Apologies if this has been asked before, I’ve searched in the support docs and can’t find what I’m looking for


1 Like

It doesn’t seem like Hugo reads a .env file automatically so you will need to source it before you run the hugo command. Maybe make a feature request for this.

A .env file like this:


Then run:

source .env

After that you can access the variable in a Hugo template with:

{{ getenv "HUGO_gtm" }}

The “HUGO_” part in the variable name is optional but since Hugo uses it for all it’s built in variables I think it’s a good idea to use throughout.


Consider making the theme its own repo; then you can keep your site configuration private. :slight_smile:

Hi @frjo

Thank you. Unfortunately when I run

source .env

in my terminal in the root folder of the project, nothing happens. If I run

hugo source .env

I get an error message

error: unknown command “source” for “hugo”

and if I run

hugo -s .env

I get the error

Error: Unable to locate config file or config directory. Perhaps you need to create a new site.

I’m not sure how to make Hugo read from the .env file. I have tried placing the .env in the projects root folder, and the themes root folder

Hi @maiki

Thank you for the suggestion, agreed yes I’d be able to keep api keys private.

I’m not sure it solves my issue of trying to make Hugo access the variables the .env file?

I could aways put the api keys in the config file (in a private repo), but it doesn’t seem to be best practise. I run the risk of accidentally committing the config file to a public repo in the future. I can (and have) set up my gitignore to exclude .env files.

You’ll need to look up what source does:

In this context this is allowing you to save your variable and read it, but it is just the step at

Meaning, when you build your project you either source and set your env, or some other way; many continuous integration/deployment tools grab these from a repo hosting app, saved privately outside the repo itself.

I didn’t look at your repo, just your use case. My build repos are single config files that mount content and themes via modules. If I’m just testing something out, I’ll drop domain-specific credentials into a private repo. Otherwise I’d use environment variables. :slight_smile:

But I get what you are trying to do. Look up how to export env variables from a text file for your OS and you should be golden.

Thank you @maiki for your advice, I’ll let you know how I get on

Did you find a way @hugo_elliot ?

Unfortunately not

$ export HUGO_PARAMS_XXX_KEY=1234567890ABCDEFG

{{ getenv "HUGO_PARAMS_XXX_KEY" }}

Did you try using ‘secrets’ in your github repository @hugo_elliott ? Secrets on repo are controlled and you can decide who can see them.

Do you know how to trick getenv with github-action ?
I was doing this
{{- $mysecretKey := getenv "HUGO_MY_SECRET_KEY" -}}
and define it inside secret key and github workflows


But still got nothing…

This works for me, you could try it (use with: in your yml file):


Have confirmed that Hugo accesses “secret” environment variables from the host at build time (and am aware of the 0.91.0+ security policy config), but it sure would be nice if we could use a gitignored .env file, or something like it, during local development, such as when working with a private API that requires credentials for access. While one certainly can feed environment variables to Hugo in the terminal, that gets unwieldy with more than a small number of these vars. Anybody got a solution that’s anything like the convenience of a local gitignored .env file? (I had no luck with the source .env suggestion mentioned above, including doing it as one command — e.g., source .env && hugo server — to see if that would pass the .env contents to Hugo.)

Which OS?

Sorry, should have mentioned that; macOS (12.x, if that matters). Guess Linux users would have same question, of course.

It stays out of your way until it can’t, then it lets you know what it’s doing.

1 Like

Very interesting! Thanks.

Edit: And it works like a charm. Excellent.