Skip to content

Adding your own containers to Saltbox

Description / nameInput element
Your domain name
Your app's name
Your container's application data path

Use this guide to extend your setup beyond the stock catalog. While arbitrary deployments fall outside our support scope, we offer resources to facilitate their integration with the Saltbox ecosystem.

Docker Compose

Recommended for GUI applications and web services.

  1. Run the interactive role to generate a Compose file with Traefik configuration:

    sb install generate-traefik-template
    

    The file will be saved as /tmp/docker-compose.yml.

  2. Create the application directory (under /opt is recommended, for consistency and backup purposes)

    mkdir /opt/appname
    
  3. It is recommended to store the Compose file in the root of the application directory:

    mv /tmp/docker-compose.yml /opt/appname/compose.yaml
    
  4. Edit /opt/appname/compose.yaml as appropriate for your application.

    • Always needs changing:

      image: your_image:your_tag
      
    • Often needs changing:

      environment:
        # Remove unsupported environment variables and add image-specific ones, e.g.:
        SOME_SETTING: "myvalue" # (1)!
        OTHER_SETTING: "true"
      
      1. List syntax is also supported:

        environment:
          - SOME_SETTING="myvalue"
          - OTHER_SETTING="true"
        
      volumes:
        - /opt/appname:/config # (1)!
        # Set other volume mappings the image requires
      
      1. Image may use a different path than /config
    Cheat Sheet (some content may be outdated)
    services:
      appname:
        restart: unless-stopped # (1)!
        container_name: appname # (2)!
        image: DOCKER/IMAGE:TAG # (3)!
        hostname: appname # (4)!
        environment: # (5)!
          PUID: "1000"
          PGID: "1000"
          TZ: "Etc/UTC"
        networks: # (6)!
          - saltbox
        labels:
          com.github.saltbox.saltbox_managed: true # (7)!
          diun.enable: true # (8)!
          traefik.enable: true # (9)!
          traefik.http.routers.appname-api-http.entrypoints: web # (10)!
          traefik.http.routers.appname-api-http.middlewares: globalHeaders@file,redirect-to-https@docker,robotHeaders@file,cloudflarewarp@docker # (11)!
          traefik.http.routers.appname-api-http.priority: 99 # (12)!
          traefik.http.routers.appname-api-http.rule: Host(`appname.yourdomain.tld`) && (PathPrefix(`/api`) || PathPrefix(`/ping`)) # (13)!
          traefik.http.routers.appname-api-http.service: appname # (14)!
          traefik.http.routers.appname-api.entrypoints: websecure # (15)!
          traefik.http.routers.appname-api.middlewares: globalHeaders@file,secureHeaders@file,robotHeaders@file,cloudflarewarp@docker # (16)!
          traefik.http.routers.appname-api.priority: 99 # (17)!
          traefik.http.routers.appname-api.rule: Host(`appname.yourdomain.tld`) && (PathPrefix(`/api`) || PathPrefix(`/ping`)) # (18)!
          traefik.http.routers.appname-api.service: appname # (19)!
          traefik.http.routers.appname-api.tls.certresolver: cfdns # (20)!
          traefik.http.routers.appname-api.tls.options: securetls@file # (21)!
          traefik.http.routers.appname-http.entrypoints: web # (22)!
          traefik.http.routers.appname-http.middlewares: globalHeaders@file,redirect-to-https@docker,robotHeaders@file,cloudflarewarp@docker,authelia@docker # (23)!
          traefik.http.routers.appname-http.rule: Host(`appname.yourdomain.tld`) # (24)!
          traefik.http.routers.appname-http.service: appname # (25)!
          traefik.http.routers.appname.entrypoints: websecure # (26)!
          traefik.http.routers.appname.middlewares: globalHeaders@file,secureHeaders@file,robotHeaders@file,cloudflarewarp@docker,authelia@docker # (27)!
          traefik.http.routers.appname.rule: Host(`appname.yourdomain.tld`) # (28)!
          traefik.http.routers.appname.service: appname # (29)!
          traefik.http.routers.appname.tls.certresolver: cfdns # (30)!
          traefik.http.routers.appname.tls.options: securetls@file # (31)!
          traefik.http.services.appname.loadbalancer.server.port: APPLICATION_PORT # (32)!
        volumes: # (33)!
          - /opt/appname:/config
          - /etc/localtime:/etc/localtime:ro # (34)!
    
    networks: # (35)!
      saltbox:
        external: true
    
    1. Defines the container's restart policy. Reference

    2. Defines the name of the container.

    3. Defines the image and tag used when creating the container.

    4. Defines the hostname used on the Docker network.

    5. Defines the environment variables which are often used to change configuration of the underlying application inside of the container.

      While the TZ (Timezone) variable is used in pretty much all containers, you will have to figure out the rest as it can differ quite a bit between different containers.

    6. Defines which Docker networks the container will join upon creation.

      We generally recommend using the saltbox network unless you know what you are doing.

    7. This label will tell Saltbox to manage the container during backups (stopping and starting it).

    8. (Optional) If diun is installed, this label will allow the container to be monitored for updates.

    9. This label enables router creation in Traefik.

    10. Defines the entrypoint used for the HTTP Traefik router.

      Leave as is unless you know what you are doing.

    11. Defines which middleware is used on the router.

      A list of currently added middleware can be found on the Traefik dashboard (dash.yourdomain.tld).

      Unless you intend to allow HTTP traffic instead of auto-upgrading to HTTPS, make sure to include the redirect-to-https middleware.

    12. Defines router priority.

      If multiple router paths match a given address, the one with the highest priority is used.

    13. This value defines which locations Traefik routes to the application.

      With the API Router, we only add paths to the router that should bypass Authelia.

      Docs: https://doc.traefik.io/traefik/routing/routers/#rule

    14. Defines which service the router should route traffic to.

    15. Defines the entrypoint used for the HTTP Traefik router.

      Leave as is unless you know what you are doing.

    16. Defines which middleware is used on the router.

      A list of currently added middleware can be found on the Traefik dashboard (dash.yourdomain.tld).

    17. Defines router priority.

      If multiple router paths match a given address, the one with the highest priority is used.

    18. This value defines which locations Traefik routes to the application.

      With the API Router, we only add paths to the router that should bypass Authelia.

      Docs: https://doc.traefik.io/traefik/routing/routers/#rule

    19. Defines which service the router should route traffic to.

    20. Defines the certificate resolver to use in order to generate a certificate.

      If the url is using Cloudflare, with the same account as Saltbox uses, the value should be cfdns.

      If you don't use Cloudflare with the URL used, or for another reason it cannot use DNS validation, use httpresolver.

      Remember to enable http_validation in the adv_settings.yml config to enable the httpresolver when using Cloudflare.

    21. Defines the configuration used for SSL, leave this alone unless you know what you are doing.

    22. Defines the entrypoint used for the HTTP Traefik router.

      Leave as is unless you know what you are doing.

    23. Defines which middleware is used on the router.

      A list of currently added middleware can be found on the Traefik dashboard (dash.yourdomain.tld).

      Unless you intend to allow HTTP traffic instead of auto-upgrading to HTTPS, make sure to include the redirect-to-https middleware.

    24. This value defines which locations Traefik routes to the application.

      Docs: https://doc.traefik.io/traefik/routing/routers/#rule

    25. Defines which service the router should route traffic to.

    26. Defines the entrypoint used for the HTTP Traefik router.

      Leave as is unless you know what you are doing.

    27. Defines which middleware is used on the router.

      A list of currently added middleware can be found on the Traefik dashboard (dash.yourdomain.tld).

    28. This value defines which locations Traefik routes to the application.

      Docs: https://doc.traefik.io/traefik/routing/routers/#rule

    29. Defines which service the router should route traffic to.

    30. Defines the certificate resolver to use in order to generate a certificate.

      If the url is using Cloudflare, with the same account as Saltbox uses, the value should be cfdns.

      If you don't use Cloudflare with the URL used, or for another reason it cannot use DNS validation, use httpresolver.

      Remember to enable http_validation in the adv_settings.yml config to enable the httpresolver when using Cloudflare.

    31. Defines the configuration used for SSL, leave this alone unless you know what you are doing.

    32. Defines which port Traefik routes the traffic to.

    33. Add any volume mounts the container needs.

      /host_path:/container_path

    34. Maps the host's timezone to the container's.

      This is an alternative to the TZ environment variable.

    35. This section tells Docker Compose that the network is managed outside of this compose file.

  5. Ensure a DNS A record exists that points to the application (e.g., appname.yourdomain.tld). This can be achieved by creating it manually, by running DDNS (Cloudflare only), or through a wildcard DNS record.

  6. Deploy and start the container:

    cd /opt/appname
    docker compose up -d
    
  7. Access your application at https://iCUSTOM_APP_FQDNi.

Docker CLI

Recommended for command‑line utilities where a container is invoked ad hoc or on a schedule.

While such containers can be run via Compose, you may prefer to avoid the extra files. Optionally, register them as functions in your shell environment, so they can be called in their native, host-level form.

appname() {
  docker run --rm -it \
    DOCKER/IMAGE:TAG "$@"
}
shell_bash_bashrc_block_custom
shell_bash_bashrc_block_custom: |

  appname() {
    docker run --rm -it \
      DOCKER/IMAGE:TAG "$@"
  }
shell_zsh_zshrc_block_custom
shell_zsh_zshrc_block_custom: |

  appname() {
    docker run --rm -it \
      DOCKER/IMAGE:TAG "$@"
  }

Then call from your regular shell with a command such as appname --help.

Example

yt-dlp() {
  docker run --rm -it \
    -v "$(pwd)":/downloads:rw \
    -u $(id -u):$(id -g) \
    ghcr.io/jauderho/yt-dlp:latest "$@"
}
speedtest() {
  docker run --rm -it \
    gists/speedtest-cli "$@"
}
shell_bash_bashrc_block_custom
shell_bash_bashrc_block_custom: |

  yt-dlp() {
    docker run --rm -it \
      -v "$(pwd)":/downloads:rw \
      -u $(id -u):$(id -g) \
    ghcr.io/jauderho/yt-dlp:latest "$@"
  }

  speedtest() {
    docker run --rm -it \
      gists/speedtest-cli "$@"
  }
shell_zsh_zshrc_block_custom
shell_zsh_zshrc_block_custom: |

  yt-dlp() {
    docker run --rm -it \
      -v "$(pwd)":/downloads:rw \
      -u $(id -u):$(id -g) \
    ghcr.io/jauderho/yt-dlp:latest "$@"
  }

  speedtest() {
    docker run --rm -it \
      gists/speedtest-cli "$@"
  }

Call using yt-dlp and speedtest commands.

Ansible Roles

Recommended when you need more automation and are comfortable working with YAML and Jinja2.

saltbox_mod