Project One-Click: All-in-One Installations of Docker Extensions and CDVR Custom Channels

Here are my new variables:

> DOMAIN=
> HOST_PORT=1337
> CHANNELS_DVR_HOST=192.168.150.242
> CHANNELS_DVR_PORT=8089
> CHANNELS_DVR2_HOST=
> CHANNELS_DVR2_PORT=
> CHANNELS_DVR3_HOST=
> CHANNELS_DVR3_PORT=
> CHANNELS_CLIENTS=192.168.150.231 192.168.150.194 146.12.197.19 192.168.150.177
> ALERT_SMTP_SERVER=smtp.gmail.com:587
> [email protected]
> ALERT_EMAIL_PASS=redacted
> [email protected]
> UPDATE_YAMLS=true
> UPDATE_SCRIPTS=true
> TZ=US/Central
> HOST_DIR=/Users/jasontrippe
> DVR_SHARE=Volumes/External Drive/Channels DVR
> LOGS_SHARE=Volumes/External Drive/Channels DVR
> TUBEARCHIVIST_SHARE=Volumes/External Drive/Channels DVR
> DVR2_SHARE=
> LOGS2_SHARE=
> TUBEARCHIVIST2_SHARE=
> DVR3_SHARE=
> LOGS3_SHARE=
> TUBEARCHIVIST3_SHARE=
> HOST_SFS_PORT=8080
> FOLDER=/web
> PORTAINER_TOKEN=redacted
> PORTAINER_HOST=docker-host
> PORTAINER_PORT=9443
> PORTAINER_ENV=2
> PERSISTENT_LOGS=false

Looking better, though I'm sure your CDVR programs are not stored here. But let's leave this one as-is for the moment.

I'm almost certain this is wrong, as it's the sample value. If you're running on a Mac (which it looks like you are), and you have CDVR and Docker/Portainer all on the same computer -- then this value would be 192.168.150.242 too.

This seems wrong as well, as your Channels clients should all be on the same subnet, i.e. 192.168.150.xxx. What's with the 146.12.197.19 value?

Ok, I changed the portainer host. That didn't work. The 146 domain is correct. It is my in-laws house. Do I have to list every single client, as there are a bunch for us?

The client IPs are mostly for sending messages to all clients, and you only need to list those on your local network. Remote systems could only be reached if you used Tailscale.

What do you mean by this? Are you seeing the exact same error message? If not, please post the new error.

I changed the Portainer host to my local domain. The error looks the same:

> failed to deploy a stack: time="2025-07-03T00:37:44Z" level=warning msg="The \"EZ_START\" variable is not set. Defaulting to a blank string." time="2025-07-03T00:37:44Z" level=warning msg="The \"EZ_START\" variable is not set. Defaulting to a blank string." time="2025-07-03T00:37:44Z" level=warning msg="The \"EZ_START\" variable is not set. Defaulting to a blank string." time="2025-07-03T00:37:44Z" level=warning msg="The \"EZ_START\" variable is not set. Defaulting to a blank string." services.olivetin.volumes array items[4,7] must be unique```

I see it now. As the error suggests the problem is with the above. Without a leading slash these paths are assumed to be volumes -- which is not what you're intending. Add the leading slashes to indicate directory paths, and you should be good.

Changed to the below and still the same error:

DVR_SHARE=/Volumes/External Drive/Channels DVR
LOGS_SHARE=/Volumes/External Drive/Channels DVR
TUBEARCHIVIST_SHARE=/Volumes/External Drive/Channels DVR

Could you post the Docker compose you're using for OliveTin please?

See below.

> version: '3.9'
> services:
>   olivetin: # This docker-compose typically requires no editing. Use the Environment variables section of Portainer to set your values.
>     # 2025.03.27
>     # GitHub home for this project: https://github.com/bnhf/OliveTin.
>     # Docker container home for this project with setup instructions: https://hub.docker.com/r/bnhf/olivetin.
>     image: bnhf/olivetin:${TAG:-latest} # Add the tag like latest or test to the environment variables below.
>     container_name: ${OLIVETIN_NAME:-olivetin}${EZ_START}
>     hostname: ${OLIVETIN_NAME:-olivetin}${EZ_START}
>     dns_search: ${DOMAIN:+${DOMAIN}} # For Tailscale users using Magic DNS, add your Tailnet (tailxxxxx.ts.net) to use hostnames for remote nodes, otherwise use your local domain name.
>     ports:
>       - ${HOST_PORT:-1337}:1337
>     environment:
>       - OLIVETIN_COMPOSE=2025.03.26${EZ_START} # Do not change this value.
>       - CHANNELS_DVR=${CHANNELS_DVR_HOST}:${CHANNELS_DVR_PORT:-8089} # Add your Channels DVR server in the form CHANNELS_DVR_HOST=<hostname or ip> and CHANNELS_DVR_PORT=<port>.
>       - ${CHANNELS_DVR2_HOST:+CHANNELS_DVR_ALTERNATES=${CHANNELS_DVR2_HOST}:${CHANNELS_DVR2_PORT}} ${CHANNELS_DVR3_HOST:+${CHANNELS_DVR3_HOST}:${CHANNELS_DVR3_PORT}} # Space separated list of alternate Channels DVR servers to choose from in the form hostname:port or ip:port.
>       - CHANNELS_CLIENTS=${CHANNELS_CLIENTS} # Space separated list of Channels DVR clients you'd like notifications sent to in the form hostname or IP.
>       - ALERT_SMTP_SERVER=${ALERT_SMTP_SERVER} # SMTP server to use for sending alert e-mails. smtp.gmail.com:587 for example.
>       - ALERT_EMAIL_FROM=${ALERT_EMAIL_FROM} # Sender address for alert e-mails.
>       - ALERT_EMAIL_PASS=${ALERT_EMAIL_PASS} # SMTP "app" password established through GMail or Yahoo Mail. Do not use your everyday e-mail address.
>       - ALERT_EMAIL_TO=${ALERT_EMAIL_TO} # Recipient address for alert e-mails.
>       - UPDATE_YAMLS=${UPDATE_YAMLS:-true} # Set this to true to update config.yaml.
>       - UPDATE_SCRIPTS=${UPDATE_SCRIPTS:-true} # Set this to true to update all included scripts.
>       - TZ=${TZ} # Add your local timezone in standard linux format. E.G. US/Eastern, US/Central, US/Mountain, US/Pacific, etc.
>       - PORTAINER_TOKEN=${PORTAINER_TOKEN} # Generate via <username> dropdown (upper right of WebUI), "My account", API tokens.
>       - PORTAINER_HOST=${PORTAINER_HOST:-$CHANNELS_DVR_HOST} # Hostname or IP of the Docker host you're running Portainer on.
>       - PORTAINER_PORT=${PORTAINER_PORT:-9443} # https port you're running Portainer on. 9443 is the default.
>       - PORTAINER_ENV=${PORTAINER_ENV:-2} # Set this is if you're using an alternate Portainer Environment for some reason. 2 is the default.
>       - PERSISTENT_LOGS=${PERSISTENT_LOGS:-false} # For supported Actions, log files are retained on an ongoing basis. false is the default.
>     volumes:
>       - ${HOST_DIR:-/unused}${HOST_DIR:+/olivetin:/config} # Add the parent directory on your Docker you'd like to use.
>       - ${DVR_SHARE:-/unused}${DVR_SHARE:+:/mnt/${CHANNELS_DVR_HOST}-${CHANNELS_DVR_PORT}} # This can either be a Docker volume or a host directory that's connected via Samba or NFS to your Channels DVR network share.
>       - ${LOGS_SHARE:-/unused}${LOGS_SHARE:+:/mnt/${CHANNELS_DVR_HOST}-${CHANNELS_DVR_PORT}_logs} # This can either be a Docker volume or a host directory that's connected via Samba or NFS to your Channels DVR logs network share.
>       - ${TUBEARCHIVIST_SHARE:-/unused}${TUBEARCHIVIST_SHARE:+:/mnt/${CHANNELS_DVR_HOST}-${CHANNELS_DVR_PORT}_ta} # This can either be a Docker volume or a host directory that's connected via Samba or NFS to your TubeArchivist videos network share.
>       - ${DVR2_SHARE:-/unused}${DVR2_SHARE:+:/mnt/${CHANNELS_DVR2_HOST}-${CHANNELS_DVR2_PORT}} # Note that these volume mounts should always be to /mnt/hostname-port or /mnt/ip-port (dash rather than a colon between).
>       - ${LOGS2_SHARE:-/unused}${LOGS2_SHARE:+:/mnt/${CHANNELS_DVR2_HOST}-${CHANNELS_DVR2_PORT}_logs} # This can either be a Docker volume or a host directory that's connected via Samba or NFS to your Channels DVR logs network share.
>       - ${TUBEARCHIVIST2_SHARE:-/unused}${TUBEARCHIVIST2_SHARE:+:/mnt/${CHANNELS_DVR2_HOST}-${CHANNELS_DVR2_PORT}_ta} # This can either be a Docker volume or a host directory that's connected via Samba or NFS to your TubeArchivist videos network share.
>       - ${DVR3_SHARE:-/unused}${DVR3_SHARE:+:/mnt/${CHANNELS_DVR3_HOST}-${CHANNELS_DVR3_PORT}} # Note that these volume mounts should always be to /mnt/hostname-port or /mnt/ip-port (dash rather than a colon between).
>       - ${LOGS3_SHARE:-/unused}${LOGS3_SHARE:+:/mnt/${CHANNELS_DVR3_HOST}-${CHANNELS_DVR3_PORT}_logs} # This can either be a Docker volume or a host directory that's connected via Samba or NFS to your Channels DVR logs network share.
>       - ${TUBEARCHIVIST3_SHARE:-/unused}${TUBEARCHIVIST3_SHARE:+:/mnt/${CHANNELS_DVR3_HOST}-${CHANNELS_DVR3_PORT}_ta} # This can either be a Docker volume or a host directory that's connected via Samba or NFS to your TubeArchivist videos network share.
>       - /var/run/docker.sock:/var/run/docker.sock
>     restart: unless-stopped
> 
>   static-file-server:
>     image: halverneus/static-file-server:latest
>     container_name: ${SFS_NAME:-static-file-server}${EZ_START}
>     dns_search: ${DOMAIN}
>     ports:
>       - ${HOST_SFS_PORT:-0}:8080
>     environment:
>       - FOLDER=${FOLDER:-/web}
>     volumes:
>       - ${HOST_DIR:-/unused}${HOST_DIR:+/olivetin/data:${FOLDER:-/web}}
>     restart: unless-stopped
> 
> #0#volumes: # Remove the #x# to enable. Use this section if you've setup a docker volume named channels-dvr, with CIFS or NFS, to bind to /mnt/dvr inside the container. Set ${DVR_SHARE} to channels-dvr (DVR_SHARE=channels_dvr) in that example.
>   #1#channels-dvr:
>     #1#external: true
>   #2#channels-dvr-logs:
>     #2#external: true
>   #3#tubearchivist:
>     #3#external: true
>   #4#channels-dvr2:
>     #4#external: true
>   #5#channels-dvr2-logs:
>     #5#external: true
>   #6#tubearchivist2:
>     #6#external: true
>   #7#channels-dvr3:
>     #7#external: true
>   #8#channels-dvr3-logs:
>     #8#external: true
>   #9#tubearchivist3:
>     #9#external: true```

That looks fine. I've deployed the same compose myself in the last day or so on a Mac, so I'm not sure where this is going wrong. I'll have to test out a few theories and get back to you...

Thank you so much!

@bnhf Just a thought to consider.
I know your EZ Start was heading in this direction.
It would be so much easier for new users if there were a simplified two step setup for OT4C;

STEP 1 - Use a simplified docker compose with no environment variables just to get OT4C up & running.

  • Have an OT4C Settings page UI where users can add/change setting with good explanations of what each is for.
  • This Settings page could have links to online documentation.
  • Use a permanent/persistant Settings file to hold all settings, especially those not needed to create the container.
  • Once the user has made all the required settings in the Settings page UI, display a docker compose without environment variables to use in STEP 2.

STEP 2 - Create the finalized OT4C container using the compose statement displayed in STEP 1

  • This container will use the permanent/persistant Settings file instead of env vars.
  • This container will also have the same OT4C Settings page UI that accesses the permanent/persistant Settings file.
  • Keeping any settings not needed to create the container in the settings file will simplify things for the user.

I know you seem to like env vars in portainer stacks, but it's very confusing having to figure out from comments in the compose statements which env vars need to be set to what and which are required vs. optional and even samples can be confusing if a user is unfamiliar with host and domain names vs. IP addresses.
When I use Portainer stacks I like to include everything in the compose statement and eliminate environment variables not absolutely necessary.

Not even sure if this is possible, but if so I'm sure it would eliminate a lot of troubleshooting in setting up OT4C.

And if STEP 1 isn't possible in OT4C, perhaps it could just be a web page.

After all, whether the compose statement or environment variables are changed in a stack, it has to be redeployed.

The only environment variable I could imagine being needed is the host volume mapping for /config, storage of the persistant settings/config file
But a user could just modify the compose statement instead.
Or perhaps it could be a named docker volume (which I've never used, so not sure).

services:
  olivetin-bootstrap:
    # 2026.07.02
    # GitHub home for this project: https://github.com/bnhf/OliveTin
    # Docker container home for this project with setup instructions: https://hub.docker.com/r/bnhf/olivetin
    container_name: olivetin-bootstrap
    hostname: olivetin-bootstrap
    image: bnhf/olivetin:bootstrap
    ports:
      - 1337:1337
    environment:
      - OLIVETIN_COMPOSE=2026.07.02 # Do not change this value.
      - UPDATE_SCRIPTS=true # Set this to true to update all included scripts.
      - UPDATE_YAMLS=true # Set this to true to update config.yaml.
    volumes:
      - ${OLIVETIN_HOST_DIR}:/config # Change ${OLIVETIN_HOST_DIR} to the directory on your Docker host used to store OLIVETIN config and settings files, like /volume1/docker/olivetin If running on Synology docker, this directory must first be created by the user.
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

environment variables:

OLIVETIN_HOST_DIR=/volume1/docker/olivetin

Actually OliveTin EZ-Start is fully up-and-available. It uses the same standard OliveTin Compose, and only requires two env vars:

EZ_START=-ezstart
CHANNELS_DVR_HOST=ip.address.of.your.cdvr.server

Then there's an OliveTin Action to help build a list of the variables required. More details here:

I've even taken it to the point where it'll install Portainer as well, with an OliveTin spin-up from the command line:

Just as an aside the person I was helping today in this thread is actually not a new user, but someone that had a functioning OliveTin/Project One-Click installation earlier this year. That installation became corrupted in a way I'm still trying to get to the bottom of, mostly having to do with some missteps in using Portainer I believe. We're working through it.

1 Like

Ahh, OK :smile:
It may just be me. I just like the env vars filled out in the compose statement instead of having to look them up in a separate section of a stack. To each his own.

That works for simple composes, but for more advanced stacks there's a pretty significant advantage to being able to update the compose, and know the env vars won't disappear with the old compose.

In addition, everything in Project One-Click would be much more cumbersome to deal with -- if I was trying to embed user data in each compose. By separating compose from user data, there's a clean line between what's static and what's dynamic.

When you put your values directly in a compose it's much the same as hard coding values in scripts or programs. It's no big deal when you're doing it just for yourself, and it makes things easy to read without variables, but it's not a good practice for wider use.

I understand what you're saying.
Like I said, to each his own.
You have to support OT4C, I just have to thank you for it and use it :smile:

Yah, but I add more comments so I can understand what I hard coded in the compose :smile:

1 Like

Would you consider moving (or copying) the environment variables comments/documentation from the compose statement to the environment variables section to make it easier since that's what we're editing?

That way we don't have to look at the compose (which you don't want us to edit) to get the definition of an environment variable that we need to change in the environment variable section of the stack.

example - My Fubo container stack environment variables

FUBO_PASS=Monkey123!                   # My Fubo account password
[email protected] # My Fubo account username (usually my email address)
HOST_PORT=7777                         # this Fubo containers host port number
TZ=America/Los_Angeles                 # My local timezone in standard linux format

This could be a good compromise. I've tested this on a limited basis in the past, but I'll dig into it a bit more and make sure there aren't any gotchas.

@jtrippe77 When you have time, I think the best option at this point is for you to use the OliveTin EZ-Start process to rebuild. This should give us a better idea of whether there's underlying issue with your Portainer installation.

Please follow the steps outlined here:

I copied everything exactly as instructed in the link you provided (IP address of my server w/o 8089) and get the following error:


> failed to deploy a stack: time="2025-07-03T17:15:58Z" level=warning msg="The \"CHANNELS_DVR2_HOST\" variable is not set. Defaulting to a blank string." time="2025-07-03T17:15:58Z" level=warning msg="The \"CHANNELS_DVR2_PORT\" variable is not set. Defaulting to a blank string." time="2025-07-03T17:15:58Z" level=warning msg="The \"CHANNELS_DVR3_HOST\" variable is not set. Defaulting to a blank string." time="2025-07-03T17:15:58Z" level=warning msg="The \"CHANNELS_DVR3_PORT\" variable is not set. Defaulting to a blank string." time="2025-07-03T17:15:58Z" level=warning msg="The \"CHANNELS_CLIENTS\" variable is not set. Defaulting to a blank string." time="2025-07-03T17:15:58Z" level=warning msg="The \"ALERT_SMTP_SERVER\" variable is not set. Defaulting to a blank string." time="2025-07-03T17:15:58Z" level=warning msg="The \"ALERT_EMAIL_FROM\" variable is not set. Defaulting to a blank string." time="2025-07-03T17:15:58Z" level=warning msg="The

Maybe there is an issue with my Portainer. I see "Deploy the Stack" but not "Update Stack" like the directions.