What are .env files and how do i use them?

Why You Need a .env File

Setting up a media server with Radarr, Sonarr, Prowlarr, and SABnzbd can get complicated fast. If you’ve ever found yourself digging through your docker-compose.yml or manually editing container configurations to change a single setting, you know the pain.

Hardcoding paths, user IDs, and environment variables across multiple containers make updates a nightmare. Want to change your downloads directory? That’s at least four places you’ll need to edit. Move your media to a new drive? Even worse.

That’s where the .env file comes in.

With a .env file, you centralize all your important variables into a single, easy-to-edit file. Instead of making changes across multiple configurations, you update one file, and everything follows suit. This approach keeps your setup clean, modular, and easily portable.

Let’s dive into how to create, use, and secure a .env file to streamline your Arr stack.


Step 1: Creating the .env File

The first step is to create the .env file in the same directory as your docker-compose.yml:

In previous posts, the docker compose file lives in your home directory in the folder docker.

cd ~/docker
nano .env

The .env file is a hidden file. In fact any file that starts with . is hidden from the ls command.

Paste this in to your .env file:

# User and Group ID (Prevents permission issues)
# Main user ID
PUID=1000
# Our media group:
PGID=1001

# Timezone (Ensures correct scheduling and logs)
TZ=America/Denver

# Define Ports (Ports for each container are defined here)
RADARR_PORT=7878
SONARR_PORT=8989
PROWLARR_PORT=9696
SABNZBD_PORT=8080

# Data Directories (Keeps storage paths centralized)
CONFIG_PATH=/docker
DOWNLOADS_PATH=/media/Downloads
MEDIA_PATH=/media

Breaking Down the Variables

  • PUID & PGID – These define which user the container runs as. If you’ve ever had issues with files being created with the wrong ownership, this fixes it.
  • TZ (Time Zone) – Ensures logs and scheduled tasks (like downloads and media scans) are in the correct time zone.
  • PORT – These define the port configuration for each container.
  • CONFIG_PATH – A dedicated directory for your app settings. Keeping all config files in one place makes backups and migrations easy.
  • DOWNLOADS_PATH – Centralized directory for your download clients (SABnzbd, etc.).
  • MEDIA_PATH – This is where your completed movies and TV shows live. Your media player (like Jellyfin or Plex) will read from here. If you are following along, the media folder is located here: /media.

This .env file keeps everything in one place, so you never have to edit multiple files when making a change.

Important Note:

Ensure the CONFIG_PATH folder exists and has the correct permissions set before proceeding:

sudo mkdir /docker
sudo chown -R $USER:media /docker
sudo chmod -R 770 /docker

Step 2: Securing the .env File

Since this file stores important configuration values (and possibly API keys if you extend it), we need to lock it down:

chmod 600 ~/docker/.env

Why This Is Important

  • chmod 600 ensures only the owner can read and write the file.
  • Prevents accidental edits or unauthorized access (especially if you store sensitive data later, like API keys).

Step 3: Using the .env File in docker-compose.yml

Now, let’s modify your docker-compose.yml file to pull values from .env.

services:
  radarr:
    image: lscr.io/linuxserver/radarr
    container_name: radarr
    env_file: .env
    ports:
      - ${RADARR_PORT}:7878
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${CONFIG_PATH}/radarr:/config
      - ${DOWNLOADS_PATH}:/downloads
      - ${MEDIA_PATH}/Movies:/movies
    restart: unless-stopped

  sonarr:
    image: lscr.io/linuxserver/sonarr
    container_name: sonarr
    env_file: .env
    ports:
      - ${SONARR_PORT}:8989
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${CONFIG_PATH}/sonarr:/config
      - ${DOWNLOADS_PATH}:/downloads
      - ${MEDIA_PATH}/Shows:/tv
    restart: unless-stopped

  prowlarr:
    image: lscr.io/linuxserver/prowlarr
    container_name: prowlarr
    env_file: .env
    ports:
      - ${PROWLARR_PORT}:9696
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${CONFIG_PATH}/prowlarr:/config
    restart: unless-stopped

  sabnzbd:
    image: lscr.io/linuxserver/sabnzbd
    container_name: sabnzbd
    env_file: .env
    ports:
      - ${SABNZBD_PORT}:8080
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${CONFIG_PATH}/sabnzbd:/config
      - ${DOWNLOADS_PATH}:/downloads
    restart: unless-stopped

How This Works

  • env_file: .env automatically loads all the variables from .env, making them accessible inside the container.
  • ${CONFIG_PATH}, ${DOWNLOADS_PATH}, and ${MEDIA_PATH} dynamically replace the hardcoded paths with the values from .env.
  • If you ever need to move your media directories, just update .env, and all containers will follow suit.
  • ${PUID} and ${PGID} are used if you need to change the user or the group running the containers.
  • ${TZ} is used if you would like to change the time zone.

Step 4: Testing and Validating Your Setup

Once everything is set, bring up your stack:

docker compose up -d

To verify that the .env file is being used correctly, check the logs of any container:

docker logs radarr

You should see environment variables applied (like correct directories being loaded).

You can also inspect a container to confirm environment variables:

docker exec -it radarr env | grep CONFIG_PATH

It should return:

CONFIG_PATH=/docker

If everything checks out, you’re good to go!


Step 5: Why This Matters in the Long Run

1. Easy Updates

  • Need to move your media to a new drive? Just update .env, and every container will follow.
  • Changing the timezone? One edit in .env instead of hunting through multiple config files.

2. Portability

  • Moving to a new server? Copy docker-compose.yml and .env, and your entire stack is configured instantly.

3. Clean and Readable Configs

  • No more massive, unreadable docker-compose.yml files with long, hardcoded paths.

4. Security and Best Practices

  • Keeps sensitive info (API keys, passwords) out of docker-compose.yml for a cleaner and more secure setup.

Taking It Further: Advanced .env Use Cases

Want to level up your .env game? Here are a few extra tricks:

Use .env for API Keys (Carefully)

If you’re using a service like NZBHydra or a third-party indexer, add API keys to .env:

NZBHYDRA_API_KEY=yourapikeyhere

Then in docker-compose.yml:

environment:
  - API_KEY=${NZBHYDRA_API_KEY}

💡 Caution: Never commit .env to GitHub or public repositories! Use .gitignore to exclude it.

One file. Easy updates. No headaches.


Wrapping Up

You should now be able to access these containers from your browser like this:

  • Sonarr: http://your-server-ip:8989
  • Radarr: http://your-server-ip:7878
  • Prowlarr: http://your-server-ip:9696
  • SABnzbd: http://your-server-ip:8080

Reminder: you can find your server IP address using this command:

ip a | grep inet

A .env file is one of the simplest yet most powerful tools in your Docker toolbox. It keeps your Arr stack modular, easy to manage, and future-proof.

Set it up today and never hardcode settings again.