# Is startup.jl an acceptable place to store credentials for interactive scripts?

**URL:** <https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343>\
**Category:** General Usage\
**Tags:** security\
**Created:** [May 4, 2023, 8:39pm UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343 "2023-05-04T20:39:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mkjohnson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkjohnson/32/211111_2.png) [@mkjohnson](https://discourse.julialang.org/u/mkjohnson)\
**Post date:** [May 4, 2023, 8:39pm UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343/1 "2023-05-04T20:39:10Z")

</div>

Hi ya’ll! I had a question about using `startup.jl` in the home directory (not the project) to store credentials as environment variables.

I come from an R background, and I’m used to storing credentials in the `.Renviron` file as described [here](https://solutions.posit.co/connections/db/best-practices/managing-credentials/#use-environment-variables).

If a script involves credentials, those are retrieved using `Sys.getenv("variable_name")`–and if a user is missing these variables in their `.Renviron` file we can prompt them to fix that. This prevents passwords and such from being hard-coded in scripts and unintentionally making their way to GitHub or elsewhere.

When working with Julia interactively (eg. doing data analysis), I’ve been storing these credentials in my `startup.jl` file as environment variables and referencing them in a similar way. For example, if working with a database:

```julia
function query_db(;db_name = "") 
  user = ENV["DB_USERNAME"]
  pass = ENV["DB_PASSWORD"]
  ...
end

```

I’m curious if this is a bad design pattern or if there is some other kind of “gotcha” associated with doing this.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [May 4, 2023, 9:02pm UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343/2 "2023-05-04T21:02:25Z")

</div>

I don’t think `startup.jl` is the best place since it is shared with all your projects. If you want to connect to a project specific database, you could start having conflicts. The usual practice in Julia, Python, and elsewhere, from what I’ve seen, is `.env` files.

[DotEnv.jl](https://github.com/vmari/DotEnv.jl) is a nice package for reading `.env` files!

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [May 4, 2023, 9:06pm UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343/3 "2023-05-04T21:06:35Z")

</div>

[GitHub - JuliaPackaging/Preferences.jl: Project Preferences Package](https://github.com/JuliaPackaging/Preferences.jl) is a nice way to store project-specific config. Not sure if it’s really suitable for something sensitive like credentials, though. Would like to know other people’s opinions on the advantages of `DotEnv.jl` over a `LocalPreferences.toml`.

---

<div class="post-metadata">

**Author:** ![mkjohnson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkjohnson/32/211111_2.png) [@mkjohnson](https://discourse.julialang.org/u/mkjohnson)\
**Post date:** [May 4, 2023, 9:26pm UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343/4 "2023-05-04T21:26:28Z")

</div>

I looked into `DotEnv.jl`, I think I avoided it because the package hasn’t been updated in so long I thought maybe it had been abandoned/wasn’t supported anymore 😅

Is the persistence across projects the only downside in your view? In the very specific use-case I’m thinking of that sparked this question (an internal analytics package), a limited set of variables shared amongst all projects is not necessarily a bad thing! For example, if you’re only using one database for all your projects then it makes sense for those credentials to be accessible across projects.

But I can see how this could get messy if credentials were highly project-specific. In which case `.env` files would definitely be the best way to go as far as I can tell.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [May 4, 2023, 9:35pm UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343/5 "2023-05-04T21:35:36Z")

</div>

In general, something simple like parsing a text file into a Dictionary is going to be extremely stable and not need updates for all of the Julia v1.X series. My guess is that it would work just fine!

If you want to make something accessible to all your projects using startup, I’d still use something like .env, .YAML, or something else to separate it from the startup.jl file itself.

It’s not unheard of to share your startup.jl file with someone so they can borrow your workflow ideas, so separating credentials from code makes it just that much harder to accidentally expose them!

That said, there is no real risk that I’m aware of to hard coding into startup.jl, so I think you can just do whatever feels right!

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [May 5, 2023, 1:18am UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343/6 "2023-05-05T01:18:10Z")

</div>

I’ll admit, `.env` is just me being stuck in my ways. I used it before Julia, so learning a Julia specific thing just hasn’t been a priority. That said, it does look very cool!

I guess one advantage is that `.env` is that it’s language agnostic so if you have a multilingual project, you don’t have to duplicate configurations. Starting up a python virtual environment with `pipenv` automatically picks up the `.env` file and loads them to the environment variables for you, which is nice.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [May 5, 2023, 5:56am UTC](https://discourse.julialang.org/t/is-startup-jl-an-acceptable-place-to-store-credentials-for-interactive-scripts/98343/7 "2023-05-05T05:56:28Z")

</div>

If the credentials are more related to a local package than to a specific project/environment, I usually store them in the package’s [Scratch space](https://github.com/JuliaPackaging/Scratch.jl).

E.g.

```julia
using Scratch
import TOML

function set_token(token)
    config_dir = @get_scratch!("config")
    config_filename = joinpath(config_dir, "config.toml")
    open(config_filename, "w") do f
        TOML.print(f, Dict("token" => token))
    end
    # Set read/write permission for the user and no permissions for others.
    chmod(config_filename, 0o600)
    return
end

function get_token()
    config_dir = @get_scratch!("config")
    config_filename = joinpath(config_dir, "config.toml")
    if !isfile(config_filename)
        error("Set personal access token with `set_token`.")
    end
    config = TOML.parsefile(config_filename)
    return config["token"]
end

```
