# Referencing environment variables

## Use case

We want to move important or frequently changing configuration values (e.g.,
passwords and other secrets) to environment variables and then reference them in
the [data model code][ref-data-model-syntax] and [configuration files][ref-config-files].

It would prevent these values from being stored in a source code repository and
being exposed to more people than needed. It would also allow to update the
deployment configuration without changing the source code.

## Configuration

In Cube Core, you can put environment variables into [`docker-compose.yml`][ref-docker-compose-config].
In Cube Cloud, you can manage environment variables via the <Btn>Settings</Btn>
page of your deployment.

### `cube.py` file

In the `cube.py` configuration file, you can access environment variables either
via the `getenv` function or the `environ` dictionary from the `os` package.
`getenv` returns `None` if the variable is not set and allows to provide a default
value. `environ` raises a `KeyError` if the variable is not set.

```python filename="cube.py"
import os

value_or_none = os.getenv('MY_ENV_VAR')
print(value_or_none)

value_or_default = os.getenv('MY_OTHER_ENV_VAR', 'my_default_value')
print(value_or_default)

value_or_error = os.environ['MY_OTHER_ENV_VAR']
print(value_or_error)
```

### `cube.js` file

In the `cube.js` configuration file, you can access environment variables via the
global `process.env` object. It returns `undefined` if the variable is not set.
You can use the `||` operator to provide a default value.

```javascript filename="cube.js"
value_or_undefined = process.env.MY_ENV_VAR
console.log(value_or_undefined)

value_or_default = process.env.MY_OTHER_ENV_VAR || 'my_default_value'
console.log(value_or_default)
```

## Data modeling

### YAML files

In YAML data model files, you can access environment variables via the built-in
`env_var` Jinja function. It raises an error if the variable is not set and allows
to provide a default value.

```yaml filename="model/cubes/my_cube.yml"
cubes:
  - name: my_cube
    description: "{{ env_var('MY_ENV_VAR') | safe }}"
    sql_table: "{{ env_var('MY_OTHER_ENV_VAR', 'my_default_value') | safe }}.table"
 
    measures:
      - name: count
        type: count
```

### `globals.py` file

In the [`globals.py` file][ref-python-globals], similarly to the [`cube.py`
file](#cubepy-file), you can access environment variables either via the `getenv`
function or the `environ` dictionary from the `os` package.

Consider the following file structure:

```tree
.
└── model
    └── globals.py
    └── cubes
        └── my_cube.yml
```

You can access environment variables in the `globals.py` file and potentially
[expose them to Jinja templates][ref-template-context] via `TemplateContext`:

```python filename="model/globals.py"
from cube import TemplateContext
import os

template = TemplateContext()

value_or_none = os.getenv('MY_ENV_VAR')
template.add_variable('value_or_none', value_or_none)

value_or_default = os.getenv('MY_OTHER_ENV_VAR', 'my_default_value')
template.add_variable('value_or_default', value_or_default)
```

```yaml filename="model/cubes/my_cube.yml"
cubes:
  - name: my_cube
    description: "{{ value_or_none | safe }}"
    sql_table: "{{ value_or_default | safe }}.table"
 
    measures:
      - name: count
        type: count
```

### JavaScript files

In JavaScript data model files, the global `process.env` object is [not
available][ref-nodejs-globals]. However, you can use that object in JavaScript
files *outside of the data model directory* and import from those files.

Consider the following file structure:

```tree
.
├── env.js
└── model
    └── cubes
        └── my_cube.js
```

You can't access `process.env` in the `my_cube.js` file but you can do that in
the `env.js` file since it's outside of the `model` directory:

```javascript filename="env.js"
module.exports = {
  value_or_undefined: process.env.MY_ENV_VAR,
  value_or_default: process.env.MY_OTHER_ENV_VAR || 'my_default_value'
}
```

```javascript filename="model/cubes/my_cube.js"
import { value_or_undefined, value_or_default } from '../env'

cube(`my_cube`, {
  description: `${value_or_undefined}`,
  sql_table: `${value_or_default}.table`,
  
  measures: {
    count: {
      type: `count`
    }
  }
})
```


[ref-data-model-syntax]: /product/data-modeling/syntax
[ref-config-files]: /product/configuration#cubepy-and-cubejs-files
[ref-docker-compose-config]: /product/deployment/core#configuration
[ref-python-globals]: /product/data-modeling/dynamic/jinja#python
[ref-template-context]: /product/data-modeling/reference/cube-package#templatecontext-class
[ref-nodejs-globals]: /product/data-modeling/dynamic/schema-execution-environment#nodejs-globals-processenv-consolelog-and-others