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

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.

Deploy the stack is correct for a new stack -- I'll fix that. More importantly, could you try to capture the entire error message. What you posted is cutoff at warnings, which we're not concerned with.

Below is all I can see to copy:


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

'''
I cannot see anything else, scroll or drag down.

Edit:  found another way to copy the error:

Deployment error failed to deploy a stack: time="2025-07-03T17:48:38Z" level=warning msg="The "DOMAIN" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "DOMAIN" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR2_HOST" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR2_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR3_HOST" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR3_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_CLIENTS" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "ALERT_SMTP_SERVER" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "ALERT_EMAIL_FROM" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "ALERT_EMAIL_PASS" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "ALERT_EMAIL_TO" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "TZ" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "PORTAINER_TOKEN" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR2_HOST" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR2_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR2_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR2_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR3_HOST" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR3_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR3_PORT" variable is not set. Defaulting to a blank string." time="2025-07-03T17:48:38Z" level=warning msg="The "CHANNELS_DVR3_PORT" variable is not set. Defaulting to a blank string." services.olivetin.volumes array items[0,1] must be unique```

Basically the same error as before, just with different numbers between the square brackets. I think something is up with your Portainer installation -- as this is an error I've never seen before. I'll do a bit more research and get back to you.

In the meantime, you might see about updating Portainer, as 2.27.9 is the current version.

I just followed the instructions exactly on updating Portainer, and now I cannot use it. I'm about at the end of the rope with Portainer. I may just stick with the containers I currently have but now I cannot update them.

I understand your frustration, but among the issues that come up on this forum, functional problems with Portainer are very rare. It's a solid piece of software, and once you get things on track, I think you'll find it a pleasure to use.

Obviously up to you though...

1 Like

I would like to keep moving, but the update just removed Portainer from my Docker completely. Then, I tried the olivetin and portainer install instructions on terminal and get zsh: command not found. It must be a user error but I'm copying everything exactly and entering the correct IP address

OK, some success. I've got portainer back by following the steps on the EZ start plus add portainer setting but then get stuck at Create an Olivetin stack in Portainer and get the following error:

JSON response from http://192.168.150.242:9000/api/stacks/create/standalone/string?endpointId=:{"message":"Invalid JWT token","details":"Unauthorized"}false

I now have an olivetin container in Docker but it won't startup and I see the EZstart container in Portainer