diff --git a/.env.local.sz b/.env.local.sz new file mode 100644 index 0000000..9a741de --- /dev/null +++ b/.env.local.sz @@ -0,0 +1,25 @@ +# user-config/.env..local.yml +ACME_EMAIL=acme.szk.li@reg.lksz.me +#CF_DNS_API_TOKEN=ArkB0sbzv-dHVjTrum-MxQuDtpdhNrbi5feyiXDa + +HOST_UID=2001 +HOST_GID=1000 + +INTERNAL_IP=192.168.222.5 + +# RUNTIPI's root on the docker host +# TIPI_VERSION=v3.8.0 +# RUNTIPI_ROOT_FOLDER_HOST=/mnt//data/apps/runtipi +# RUNTIPI_ROOT_FOLDER_HOST=/srv/runtipi +RUNTIPI_ROOT_FOLDER_HOST=/mnt/szmedia/_apps.docker/runtipi + +# ALT_ROOT_DOMAIN= # optional, alternative public domain +ROOT_DOMAIN=szk.li +DOMAIN=szk.li +LOCAL_DOMAIN=tipi.local +ALT_ROOT_DOMAIN=lksz.me + +TZ=America/New_York + +# vi: ft=sh + diff --git a/.env.local.tmpl b/.env.local.tmpl old mode 100755 new mode 100644 index 3f7e9f7..72984d5 --- a/.env.local.tmpl +++ b/.env.local.tmpl @@ -1,5 +1,20 @@ -ACME_EMAIL= -CF_DNS_API_TOKEN= +# user-config/.env..local.yml +ACME_EMAIL="" -SZ_USER_UID= -SZ_USER_GID= +HOST_UID="" +HOST_GID="" + +INTERNAL_IP="" + +# RUNTIPI's root on the docker host +# TIPI_VERSION="v3.8.0" +RUNTIPI_ROOT_FOLDER_HOST="/mnt//data/apps/runtipi" + +# ALT_ROOT_DOMAIN= # optional, alternative public domain +ROOT_DOMAIN= +DOMAIN= +LOCAL_DOMAIN=tipi.local + +TZ="America/New_York" + +# vi: ft=sh diff --git a/.env.local.tuffy.dotenv b/.env.local.tuffy.dotenv new file mode 100644 index 0000000..f86a600 --- /dev/null +++ b/.env.local.tuffy.dotenv @@ -0,0 +1,22 @@ +# user-config/.env.local.tuffy.dotenv +ACME_EMAIL=acme.admin@shefet.net + +HOST_UID=3000 +HOST_GID=3000 + +INTERNAL_IP=192.168.2.16 + +# RUNTIPI's root on the docker host +# TIPI_VERSION="v3.8.0" +RUNTIPI_ROOT_FOLDER_HOST=/mnt/shefet/data/apps/runtipi +ROOT_FOLDER_HOST=/mnt/shefet/data/apps/runtipi + +# ALT_ROOT_DOMAIN= # optional, alternative public domain +TRAEFIK_STATIC=httponly +ROOT_DOMAIN= +DOMAIN= +LOCAL_DOMAIN=tipi.tuffy.lan + +TZ=America/New_York + +# vi: ft=sh diff --git a/.env.local.wolfpack.dotenv b/.env.local.wolfpack.dotenv new file mode 100644 index 0000000..b2c9079 --- /dev/null +++ b/.env.local.wolfpack.dotenv @@ -0,0 +1,20 @@ +# user-config/.env..local.yml +ACME_EMAIL=acme.admin@shefet.net + +HOST_UID=3000 +HOST_GID=3000 + +INTERNAL_IP=192.168.2.33 + +# RUNTIPI's root on the docker host +# TIPI_VERSION="v3.8.0" +RUNTIPI_ROOT_FOLDER_HOST=/mnt/wolfpack/data/apps/runtipi + +# ALT_ROOT_DOMAIN= # optional, alternative public domain +ROOT_DOMAIN=shefet.net +DOMAIN=shefet.net +LOCAL_DOMAIN=tipi.wolfpack.lan + +TZ="America/New_York" + +# vi: ft=sh diff --git a/.gitignore b/.gitignore index 9211050..8554309 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,17 @@ -.env.local -_copy_to_traefik/tls -**/app.env +# These will be a local sym-link +*.local +*.local.yml +# local env should not be committed +app.env +# local data should always be in a subdir named local, and never committed +**/local +# traefik/tls and /sahred shouldn't exist, but in case they are copied over - don't commit them +_traefik/tls +_traefik/shared +# make it eash to disable stuff without committing +tmp.* +*.tmp +*.off + +_secrets/* +!_secrets/README.md diff --git a/_bin/checkver.sh b/_bin/checkver.sh new file mode 100755 index 0000000..ebcfe5e --- /dev/null +++ b/_bin/checkver.sh @@ -0,0 +1,49 @@ +#! /usr/bin/env bash +SCRIPT_DIR=${SCRIPT_DIR:-"$( cd -- "$( dirname -- "$0" )" &> /dev/null && pwd )"} + +# Function to compare semantic versions +compare_major_version() { + local major_version1=$(echo $1 | cut -d. -f1) + local major_version2=$(echo $2 | cut -d. -f1) + + if [[ "$major_version1" == "$major_version2" ]]; then + return 0 + else + return 1 + fi +} + +# Get Current Version of Runtipi +runtipi_path=${RUNTIPI_DIR:-"$(cd -- "${SCRIPT_DIR}/../.." &> /dev/null && pwd )"} +[ -r "$runtipi_path/VERSION" ] || runtipi_path=${RUNTIPI_DIR:-"$(cd -- "${SCRIPT_DIR}/../../_" &> /dev/null && pwd )"} +current_version=$(cat "$runtipi_path/VERSION") + +# Get the latest release information from GitHub API +latest_release=$(curl -sL \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/runtipi/runtipi/releases/latest) + +# Extract the tag name from the release information +tag_name=$(echo "$latest_release" | grep -o '"tag_name": "[^"]*' | cut -d'"' -f4) + +printf 'current: %-10s online: %-10s\n' "$current_version" "$tag_name" >&2 +# Compare major version numbers +compare_major_version "$tag_name" "$current_version" +# major_version_match=$? +# +# # Check if major versions are the same and if the latest release is newer than the current version +# if [[ $major_version_match -eq 0 ]] && [[ "$tag_name" > "$current_version" ]]; then +# echo "A new release is available: $tag_name" +# cd $runtipi_path +# echo "Backing up current version" +# if [ ! -d "$runtipi_path/backups" ]; then +# mkdir -p $runtipi_path/backups +# fi +# tar -czvf runtipi-backup-$current_version.tar.gz --exclude=media --exclude=backups * +# mv runtipi-backup-$current_version.tar.gz $runtipi_path/backups +# echo "Starting update" +# echo $runtipi_path/runtipi-cli update latest +# else +# echo "No new release found or major version mismatch" +# fi diff --git a/_bin/rtpctl.d b/_bin/rtpctl.d new file mode 100755 index 0000000..fd3bcd1 --- /dev/null +++ b/_bin/rtpctl.d @@ -0,0 +1,367 @@ +#! /usr/bin/env bash + +RPH_UID=${RPH_UID:-${UID}} + +[ "${SUDO}" == "sudo" ] || SUDO= + +# Identify source path (even if symlinked) +SOURCE=${BASH_SOURCE[0]} +while [ -L "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd ) + SOURCE=$(readlink "$SOURCE") + [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +SCRIPT_DIR=$( cd -- "$( dirname -- "${SOURCE}" )" &> /dev/null && pwd ) + +BASE_NAME="$(basename -- "$0")" +BASE_BASE_NAME="${BASE_NAME%.*}" + +RUNTIPI_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +RUNTIPI_CLI="${RUNTIPI_ROOT}/runtipi-cli" +set -e + +cd "${RUNTIPI_ROOT}" > /dev/null + +. ./user-config/.env.local + +runtipi-cli() { + if ! [ -x "${RUNTIPI_CLI}" ]; then + >&2 printf '%s\n' \ + "ERROR: ${RUNTIPI_CLI} not found or not executable!" + return 1 + fi + "${RUNTIPI_CLI}" "${@}" +} + +append_file_param() { + [ -e "${2:?File name missing}" ] || return + echo "${*}" +} + +sort-tipi() { + # 111 is followed an NBSP literal + # the 111 lines will be added only if `runtipi` is found + # sort --unique makes sure only one such line exists + # This in effect creates a methodical spacing between runtipi + # and the rest of the list + sed -Ee 's|^|555|; s|^555runtipi|111 \n000runtipi|;' \ + | sort --unique \ + | sed -Ee 's/^[[:digit:]]{3}//' +} +dls() { + local base='{{.Status}}\t{{.ID}}\t{{.Names}}\t{{.Image}}' #'\t{{.Networks}}\t{{.Ports}}\t{{.Mounts}}' + local compose='{{.Label "com.docker.compose.project"}}\t{{.Label "com.docker.compose.service"}}' + local format="table $compose\t$base" + ${SUDO} docker container ls --all --format "$format" | (sed -u '1s/.*/\U&/; q'; sort-tipi) +} + +get-docker-list() { + local POST_PROCESS=" | sed -Ee '#PP1 #PP2 #PP3' #PP_SORT" + local PP1='s/@.+//g;' + local PP2='s/ ix-/\nix-/g; s/(^|\n)ix-/\1/g;' + local PP3='' + local PP_SORT='| sort-tipi' + local SRC="" SRC_DOCKER="${SUDO} docker ps -a --format '{{.Label \"com.docker.compose.project\"}}@{{.Names}}' | sed -Ee 's/^@/<_no-compose-project_>:/;'" + local FILTER="" + local LIST='' + local MK_SEARCH_LIST="| xargs -r | sed 's/@//g; s/^/^(/; s/ *$/)@/; s/ /|/g;'" + local ARG=${1:---help} + while [ -n "$ARG" ]; do + case "$ARG" in + --debug) + set -x + ;; + -G) + POST_PROCESS="${MK_SEARCH_LIST}" + PP_SORT='' + ;; + -a) + SRC="${SRC_DOCKER}" + if [ -z "$LIST" ]; then + ARG="+X" + continue + fi + ;; + -c) + PP1='' + if [ -z "$SRC" ]; then + ARG="-r" + continue + fi + ;; + -r) + SRC="${SRC_DOCKER/ps -a /ps }" + if [ -z "$LIST" ]; then + ARG="+X" + continue + fi + ;; + +X) + PP2='' + ;; + ix|truenas) + LIST="${SUDO} find /mnt/.ix-apps/app_configs/* -maxdepth 0 -printf 'ix-%f@ '" + ;; + tp|runtipi) + LIST="${SUDO} find apps/* -maxdepth 0 -printf '%f@ ' ; echo runtipi" + ;; + other) + FILTER="grep -vE \""$(get-docker-list ix -G)"\" | grep -vE \""$(get-docker-list tp -G)"\"" + if [ -z "$LIST" ] && [ -z "$SRC" ]; then + ARG="-c" + continue + fi + ;; + *) + printf '%s %-12s %s\n' \ + "Usage:" "" ""\ + " ${BASE_NAME} ls " "" ""\ + "" "" "" \ + "Available options:" "" ""\ + "" "-G" "Create grep -E matching logic" \ + "" "-a" "All containers (including inactive ones)" \ + "" "-r" "Runing containers only" \ + "" "+X" "for IX apps - preserve the ix- prefix" \ + "" "" "" \ + "" "ix|truenas" "IX (TrueNAS SCALE) apps" \ + "" "tp|runtipi" "Runtipi apps" \ + "" "other" "All other apps" \ + && return 1 + ;; + esac + shift + ARG="${1}" + done + if [ 0 -eq "${#LIST}" ]; then + LIST="${SRC}" + SRC='' + fi + if [ 0 -eq "${#LIST}" ]; then + printf "Source missing, must specify one of the following: -a | -r | ix | tp | other\n" >&2 + return 1 + fi + POST_PROCESS="${POST_PROCESS/\#PP1/${PP1}}" + POST_PROCESS="${POST_PROCESS/\#PP2/${PP2}}" + POST_PROCESS="${POST_PROCESS/\#PP3/${PP3}}" + POST_PROCESS="${POST_PROCESS/\#PP_SORT/${PP_SORT}}" + + [ -n "$SRC" ] \ + && CLI="$SRC | grep -E \"\$(($LIST) $MK_SEARCH_LIST)\"" \ + || CLI="($LIST)" + CLI="$CLI ${FILTER:+| $FILTER} ${POST_PROCESS}" + printf '%s\n' $(eval "$CLI") +} + +list-docker-apps() { + local LIST="$(get-docker-list "$@")" + + local RUNNING="$(get-docker-list "$@" -r | sort-tipi)" + local LIMBO="$(get-docker-list "$@" -a | grep -xF "$LIST" | grep -vxF "$RUNNING" | sort-tipi)" + local DOWN="$(grep -Fxv -f <(printf '%s\n' "$RUNNING" "$LIMBO") <<<"$LIST" | sort-tipi)" + + printf 'RUNNING\n' && printf ' %s\n' ${RUNNING:-""} + [ -n "$LIMBO" ] && printf '\nLIMBO \n' && printf ' %s\n' $LIMBO || true + [ -n "$DOWN" ] && printf '\nDOWN \n' && printf ' %s\n' $DOWN || true +} + +runtipi-app-docker-compose() { + if [ $# -eq 0 ]; then + list-docker-apps tp + return 1 + fi + local APP="${1:-Must supply app name}" + + ${SUDO} docker compose \ + $(append_file_param --env-file user-config/.env.local) \ + $(append_file_param --env-file app-data/${APP}/app.env) \ + $(append_file_param --env-file user-config/${APP}/app.env) \ + --project-name ${APP} \ + $(if [ "$APP" != "runtipi" ]; then + echo --file apps/${APP}/docker-compose.yml + append_file_param --file repos/29ca930bfdaffa1dfabf5726336380ede7066bc53297e3c0c868b27c97282903/apps/docker-compose.common.yml + append_file_param --file "user-config/${APP}/docker-compose.yml" + else + append_file_param --file "docker-compose.yml" + append_file_param --file "user-config/tipi-compose.yml" + fi) \ + ${2:-ps -a} ${3:+"${@:3}"} +} + +ix-app-docker-compose() { + if [ $# -eq 0 ]; then + list-docker-apps ix + + return 1 + fi + local APP="${1:-Must supply app name}" + + DCSRC="$( + ${SUDO} find /mnt/.ix-apps/app_configs/ -type f \ + -path "*/${APP}/*/rendered/docker-compose.yaml" -printf '%T@ %p\n' \ + | sort -n | cut -d' ' -f2- | head -1 + )" + set -x + ${SUDO} docker compose "--file=${DCSRC}" "--project-name=ix-${APP}" ${2:-ps -a} ${3:+"${@:3}"} +} + +link-exists() { + local EXIT_CODE=0 + printf 'Current status:\n link: ' + ${SUDO} ip -br -c link show "${1:?Must supply device name}" 2>&1 || return 1 +} +manage-ipvlan() { + + local IPVLAN_IF="${2:-ipvlan-lan}" + local NET_IP="${NET_IP:-${INTERNAL_IP:?}}" + local IP_BASE="${NET_IP%\.[[:digit:]]*}" + local NET_IF="${NET_IF:-"$(ip -4 -br a s to "${NET_IP}" | cut -d' ' -f1)"}" + NET_IF="${NET_IF:-$($(ip -4 -br a s to "${IP_BASE}.0/24" | cut -d' ' -f1))}" + NET_IF="${NET_IF:?"Could not detect network interface for ${NET_IP}"}" + + case "${1}" in + rm) + manage-ipvlan status "${IPVLAN_IF}" && ( \ + ${SUDO} ip link delete "${IPVLAN_IF}" \ + && printf '%s\n' "${IPVLAN_IF} removed" + ) || return 1 + ;; + add) + link-exists "${IPVLAN_IF}" > /dev/null 2>&1 \ + && link-exists "${IPVLAN_IF}" || ( \ + ${SUDO} ip link add "${IPVLAN_IF}" link "${NET_IF}" type ipvlan mode l2 \ + && ${SUDO} ip addr add ${NET_IP} dev "${IPVLAN_IF}" \ + && ${SUDO} ip link set "${IPVLAN_IF}" up \ + && printf '%s\n' "${IPVLAN_IF} created"\ + && link-exists "${IPVLAN_IF}" \ + || ${SUDO} ip link delete "${IPVLAN_IF}" + ) + ;; + route) + local ROUTE_SCOPE="${3:?Must supply routing scope in the form of ###.###.###.###[/##]}" + + manage-ipvlan add "${IPVLAN_IF}" > /dev/null 2>&1 \ + && for IP in "${@:3}"; do + # Only add route if it does not already exists + printf 'Adding route for %-15s ' "$IP" + ${SUDO} ip route get "$IP" 2> /dev/null | grep -q "dev ${IPVLAN_IF} src ${NET_IP//\./\\.}" \ + && printf 'Skipping, already exists.' \ + || ${SUDO} ip route add "$IP" dev "${IPVLAN_IF}" \ + && printf '\n' \ + || (printf 'Could NOT add %s\n' "$IP" >&2; return 1) + done + + link-exists "${IPVLAN_IF}" + ;; + status) + link-exists "${IPVLAN_IF}" || return 1 + ;; + *) + printf '%s %-12s %s\n' \ + "$(manage-ipvlan status)" "" ""\ + "" "" ""\ + "Usage:" "" ""\ + " [SUDO=sudo] ${BASE_NAME} ipvlan " "" ""\ + "" "" "" \ + "Available commands:" "" ""\ + "" "" "" \ + "" "fix" "implement ipvlan fix" \ + "" "rm" "remove ipvlan fix" \ + "" "status" "output interface status" \ + return 0 + ;; + esac + + ( printf 'addr: ' && ip -4 -br -c addr show "${IPVLAN_IF}" \ + && printf 'Routes:\n' \ + && ${SUDO} ip -c route show dev "${IPVLAN_IF}" \ + | awk '{print} END{if (NR==0) print ""}' + ) 2>&1 | sed -e '/[^:]$/s/^/ /' \ + || return 1 + # ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE] [nomaster] +} + +case "${1}" in + cli) + runtipi-cli "${@:2}" + ;; + log|logs) + POSTGRES_PASSWORD=_ TIPI_VERSION=_ LOCAL_DOMAIN=_ DOMAIN=_ runtipi-app-docker-compose "${2:-runtipi}" logs ${3:+"${@:3}"} + ;; + start) + ROOT_FOLDER_HOST="${RUNTIPI_ROOT}" RUNTIPI_APP_DATA_PATH="${RUNTIPI_ROOT}" \ + runtipi-cli start --env-file user-config/.env.local ${2:---no-permissions} + ;; + update) + if [ -z "${2}" ]; then + ${SCRIPT_DIR}/checkver.sh + else + runtipi-cli update --env-file user-config/.env.local --no-permissions "${2:?Must supply version}" "${@:3}" + fi + ;; + dls) + dls "${@:2}" + ;; + ls) + get-docker-list "${@:2}" + ;; + tpcompose) + runtipi-app-docker-compose "${@:2}" + ;; + ixcompose) + ix-app-docker-compose "${@:2}" + ;; + shell) + runtipi-app-docker-compose "${2:?}" exec ${5:+"${@:5}"} -it "${4:-${2}}" "${3:-bash}" + ;; + ipvlan) + manage-ipvlan "${@:2}" + ;; + setup) + ln -s $2 "$(cd -- "${SCRIPT_DIR}" && pwd)/${BASE_NAME}" "${3:-$HOME/.local/bin/}" + ;; + edit) + ${VISUAL:-${EDITOR:-vi}} $0 + ;; + _load) + echo "alias ${BASE_NAME}cd='cd \"$SCRIPT_DIR/..\"'" + ;; + *) + printf '%s %-12s %s\n' \ + "" "" ""\ + "Usage:" "" ""\ + " [SUDO=sudo] ${BASE_NAME} [args...]" "" ""\ + "" "" "" \ + "Available commands:" "" ""\ + "" "" "" \ + "runtipi" "" ""\ + "" "cli" "runtipi-cli" \ + "" "log" "runtipi docker stack logs" \ + "" "start" "start runtipi" \ + "" "update" "update runtipi to a specific version" \ + "" "" "" \ + "docker/docker-compose" "" ""\ + "" "tpcompose" "docker compose for runtipi apps" \ + "" "ixcompose" "docker compose for ix/TrueNAS SCALE docker based app" \ + "" "ls" "list applications (or contrainers)" \ + "" "dls" "stylized docker ls" \ + "" "shell" "enter an insteractive shell" \ + "" "down-all" "stop and remove everything" \ + "" "" "" \ + "networking" "" ""\ + "" "ipvlan" "manage ipvlan networking interface fix" \ + "" "" "" \ + "misc." "" ""\ + "" "exec" "execute within the shell, START_DIR env applies" \ + "" "" "" \ + "" "setup" "setup runtipictl in user's .local/bin dir" \ + "" "" "${BASE_NAME} setup" \ + "" "" "${BASE_NAME} setup '' ~/.local/bin/${BASE_BASE_NAME}" \ + "" "" "${BASE_NAME} setup '' ~/.local/bin/runtipictl" \ + "" "" "" \ + "Related env. vars:" "" "" \ + "" "VISUAL EDITOR RPH_UID QUIET START_DIR ROOT_EXEC" "" + + ;; +esac + +# vim: set ft=sh expandtab tabstop=4 shiftwidth=4: diff --git a/_bin/rtpctl.j b/_bin/rtpctl.j new file mode 100755 index 0000000..43b8712 --- /dev/null +++ b/_bin/rtpctl.j @@ -0,0 +1,155 @@ +#! /usr/bin/env bash + +jlmkr () { + sudo VISUAL="${VISUAL:-}" EDITOR="${EDITOR:-}" $SCALE_POOL_ROOT/jailmaker/jlmkr.py "${@:---help}" +} + +RPH_UID=${RPH_UID:-${UID}} +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +BASE_NAME="$(basename "$0")" +BASE_BASE_NAME="${BASE_NAME%.*}" + +jlmkr-shell() { + if jlmkr exec runtipi true; then + jlmkr shell --uid "${RPH_UID}" runtipi + fi +} + +jlmkr-exec () { + local set_x=" set -x; pwd; id; " + [ -z "$QUIET" ] || set_x="" + local cli="cd ${START_DIR:-/srv/runtipi};${set_x} ${1:?Must supply command} " + if [ -n "$ROOT_EXEC" ]; then + cli="$cli ${*:2}" + else + cli="$cli "${2:+"$( + printf '\"%s\" ' "${@:2}" + )"} + fi + + if jlmkr exec runtipi true; then + if [ -n "$ROOT_EXEC" ]; then + jlmkr exec runtipi /bin/bash <<<"$cli" + else + jlmkr shell --uid "${RPH_UID}" runtipi /bin/bash -c "$cli" + fi + else + echo "ERROR: ${_ERROR_MGS:-"Please check if runtipi jail has started! Have you tried 'full-start'?"}" >&2 + exit -1 + fi +} + +runtipi-cli() { + jlmkr-exec ./runtipi-cli "${@}" +} + +runtipi-app-docker-compose() { + local APP="${1:-Must supply app name}" + local LOCAL_YML="user-config/${APP}/docker-compose.yml" + + jlmkr exec runtipi test -e "/srv/runtipi/${LOCAL_YML}" || LOCAL_YML="" + [ -z "$LOCAL_YML" ] || LOCAL_YML="--file ${LOCAL_YML}" + + jlmkr-exec docker compose \ + --env-file user-config/.env.local \ + --env-file app-data/${APP}/app.env \ + --env-file user-config/${APP}/app.env \ + --project-name ${APP} \ + --file apps/${APP}/docker-compose.yml \ + --file repos/29ca930bfdaffa1dfabf5726336380ede7066bc53297e3c0c868b27c97282903/apps/docker-compose.common.yml \ + ${LOCAL_YML} ${@:2} +} + +dls() { + # Default docker ps format is: + # jlmkr-exec docker ps --format "table {{ .ID }}\t{{ .Image }}\t{{ .Command }}\t{{ .Created }}\t{{ .Status }}\t{{ .Ports }}\t{{ .Names }}" + + local base='{{.Status}}\t{{.ID}}\t{{.Names}}\t{{.Image}}' #'\t{{.Networks}}\t{{.Ports}}\t{{.Mounts}}' + local compose='{{.Label "com.docker.compose.project"}}\t{{.Label "com.docker.compose.service"}}' + local format="table $compose\t$base" + ROOT_EXEC=1 QUIET=${QUIET:-0} jlmkr-exec \ + docker "container ls --all --format '$format' | ( sed -u '1s/.*/\U&/; q'; sed -Ee 's|^|555|; s|^555runtipi|000runtipi|;' | sort | sed -Ee 's/^[[:digit:]]{3}//' )" +} + +case "${1}" in + cli) + runtipi-cli "${@:2}" + ;; + log) + jlmkr-exec "POSTGRES_PASSWORD=_ TIPI_VERSION=_ LOCAL_DOMAIN=_ DOMAIN=_" docker compose --env-file user-config/.env.local logs --tail=${TAIL:-40} "${2:-runtipi}" ${3:+"${@:3}"} + ;; + start) + runtipi-cli start --env-file user-config/.env.local --no-permissions + ;; + update) + runtipi-cli update --env-file user-config/.env.local --no-permissions "${2:?Must supply version}" "${@:3}" + ;; + full-start) + if ! jlmkr exec runtipi true; then + jlmkr start runtipi + sleep 1s + fi + _ERROR_MSG="ERROR: failed to invoke a command inside the runtipi jail and can't start the jail." \ + runtipi-cli start --env-file user-config/.env.local --no-permissions + ;; + shell) + jlmkr-shell + ;; + exec) + jlmkr-exec "${@:2}" + ;; + docker) + jlmkr-exec docker "${@:2}" + ;; + dls) + dls "${@:2}" + ;; + dcoapp) + runtipi-app-docker-compose "${@:2}" + ;; + dockge) + START_DIR=/srv/dockge/stacks/${2:?Must supply stack name} jlmkr-exec docker compose "${@:3}" + ;; + setup) + ln -s $2 "$(cd "${SCRIPT_DIR}" && pwd)/${BASE_NAME}" "${3:-$HOME/.local/bin/}" + ;; + edit) + ${VISUAL:-${EDITOR:-vi}} $0 + ;; + *) + printf '%s %-12s %s\n' \ + "" "" ""\ + "Usage:" "" ""\ + " ${BASE_NAME} [args...]" "" ""\ + "" "" "" \ + "Available commands:" "" ""\ + "" "" "" \ + "runtipi" "" ""\ + "" "cli" "runtipi-cli" \ + "" "full-start" "start runtipi jail, following with starting runtipi" \ + "" "log" "runtipi docker stack logs" \ + "" "start" "start runtipi" \ + "" "update" "update runtipi to a specific version" \ + "" "" "" \ + "docker/docker-compose" "" ""\ + "" "dcoapp" "docker compose for runtipi apps" \ + "" "dls" "stylized docker ls" \ + "" "docker" "docker" \ + "" "dockge" "docker compose for dockge stacks" \ + "" "" "" \ + "misc." "" ""\ + "" "exec" "execute within the shell, START_DIR env applies" \ + "" "shell" "enter an insteractive shell" \ + "" "" "" \ + "" "setup" "setup runtipictl in user's .local/bin dir" \ + "" "" "${BASE_NAME} setup" \ + "" "" "${BASE_NAME} setup '' ~/.local/bin/${BASE_BASE_NAME}" \ + "" "" "${BASE_NAME} setup '' ~/.local/bin/runtipictl" \ + "" "" "" \ + "Related env. vars:" "" "" \ + "" "VISUAL EDITOR RPH_UID QUIET START_DIR ROOT_EXEC" "" + + ;; +esac + +# vim: set ft=sh expandtab tabstop=4 shiftwidth=4: diff --git a/_copy_to_traefik/dynamic/fwd-auth-sysmgr.yml b/_copy_to_traefik/dynamic/fwd-auth-sysmgr.yml deleted file mode 100644 index 3e91092..0000000 --- a/_copy_to_traefik/dynamic/fwd-auth-sysmgr.yml +++ /dev/null @@ -1,18 +0,0 @@ -http: - middlewares: - authentik_sysmgr: - forwardAuth: - address: https://auth.szk.li/outpost.goauthentik.io/auth/traefik - trustForwardHeader: true - authResponseHeaders: - - X-authentik-username - - X-authentik-groups - - X-authentik-email - - X-authentik-name - - X-authentik-uid - - X-authentik-jwt - - X-authentik-meta-jwks - - X-authentik-meta-outpost - - X-authentik-meta-provider - - X-authentik-meta-app - - X-authentik-meta-version \ No newline at end of file diff --git a/_copy_to_traefik/dynamic/kasm-workspaces.yml b/_copy_to_traefik/dynamic/kasm-workspaces.yml deleted file mode 100644 index 3d478bb..0000000 --- a/_copy_to_traefik/dynamic/kasm-workspaces.yml +++ /dev/null @@ -1,42 +0,0 @@ -# http routing section -http: - routers: - # Define a connection between requests and services - "to-kasm-main": - rule: "Host(`k.szk.li`)" - entrypoints: - - websecure - # # If the rule matches, applies the middleware - middlewares: - - authentik_sysmgr - # - test-user - # If the rule matches, forward to the whoami service (declared below) - service: kasm-main - tls: - certresolver: myresolver - - # Define a connection between requests and services - "to-kasm-setup": - rule: "Host(`ksetup.szk.li`)" - entrypoints: - - websecure - # # If the rule matches, applies the middleware - middlewares: - - authentik_sysmgr - # - test-user - # If the rule matches, forward to the whoami service (declared below) - service: kasm-setup - tls: - certresolver: myresolver - - - services: - # Define how to reach an existing service on our infrastructure - kasm-main: - loadBalancer: - servers: - - url: "https://kasm-workspaces:8744" - kasm-setup: - loadBalancer: - servers: - - url: "https://kasm-workspaces:8743" diff --git a/_copy_to_traefik/dynamic/kateryna_apps.yml b/_copy_to_traefik/dynamic/kateryna_apps.yml deleted file mode 100644 index a4f79c8..0000000 --- a/_copy_to_traefik/dynamic/kateryna_apps.yml +++ /dev/null @@ -1,40 +0,0 @@ -# http routing section -http: - routers: - to-auth: - rule: "Host(`auth.lksz.me`)" - entrypoints: - - websecure - service: kateryna-traefik - tls: - certresolver: myresolver - to-syncthing: - rule: "Host(`sync.lksz.me`)" - entrypoints: - - websecure - service: kateryna-traefik - tls: - certresolver: myresolver - to-kateryna: - rule: "Host(`kateryna.szk.li`) - || Host(`kateryna.lksz.me`) - || Host(`radarr.lksz.me`) - || Host(`sonarr.lksz.me`) - || Host(`prowlarr.lksz.me`) - || Host(`req.lksz.me`) - || Host(`jd.lksz.me`) - || Host(`nzb.lksz.me`) - || Host(`stats.player.lksz.me`) - " - entrypoints: - - websecure - service: kateryna-traefik - tls: - certresolver: myresolver - - services: - # Define how to reach an existing service on our infrastructure - kateryna-traefik: - loadBalancer: - servers: - - url: https://kateryna.lksz.me diff --git a/_copy_to_traefik/traefik.yml b/_copy_to_traefik/traefik.yml deleted file mode 100644 index d82af92..0000000 --- a/_copy_to_traefik/traefik.yml +++ /dev/null @@ -1,34 +0,0 @@ -api: - dashboard: true - insecure: true - -providers: - docker: - endpoint: 'unix:///var/run/docker.sock' - watch: true - exposedByDefault: false - file: - directory: /etc/traefik/dynamic - watch: true - -entryPoints: - web: - address: ':80' - http: - redirections: - entryPoint: - to: 'websecure' - scheme: 'https' - websecure: - address: ':443' - -certificatesResolvers: - httpresolver: - acme: -# email: acme@thisprops.com - storage: /shared/acme.json - httpChallenge: - entryPoint: web - -log: - level: ERROR diff --git a/_secrets/README.md b/_secrets/README.md new file mode 100644 index 0000000..b917fd4 --- /dev/null +++ b/_secrets/README.md @@ -0,0 +1,5 @@ +# runtipi's user-config secrets + +the text files in this directory are referenced in the compose yaml files in runtipi's user-config. +the files in this directory (except this README.md file) are all ignored by git + diff --git a/_template/app.env b/_template/app.env index 4d0d570..da04693 100644 --- a/_template/app.env +++ b/_template/app.env @@ -1 +1,3 @@ -# VARIABLE=value #comment# VARIABLE=value #comment +# VARIABLE=value #comment +APP_ROUTE_OPTIONAL=${ALT_ROOT_DOMAIN:+ || Host(`example.${ALT_ROOT_DOMAIN}`)} + diff --git a/_template/docker-compose.yml b/_template/docker-compose.yml index b6eb722..225fca1 100644 --- a/_template/docker-compose.yml +++ b/_template/docker-compose.yml @@ -1,19 +1,34 @@ services: : + hostname: .docker environment: - # RUNTIPI Environment + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment RUNTIPI_APP_PORT: "${APP_PORT}" RUNTIPI_APP_ID: "${APP_ID}" RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" - RUNTIPI_APP_EXPOSED: "${APP_EXPOSED}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + # volumes_from: + # - "container:vols-dl" + # - "container:vols-personal-media" + # - "container:vols-shared-media" + # - "container:vols-media" + # - "container:vols-arr" + # - "container:vols-plex" labels: # Websecure - traefik.http.routers..middlewares: authentik_sysmgr@file - # traefik.http.routers.-more.rule: Host(`.lksz.me`)${APP_ROUTE_OPTIONAL:-} + # traefik.http.routers..middlewares: authentik_sysmgr@file + traefik.http.routers..middlewares: lan-only@file + # traefik.http.routers.-more.rule: Host(`.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} # traefik.http.routers.-more.entrypoints: websecure # traefik.http.routers.-more.service: # traefik.http.routers.-more.middlewares: authentik_sysmgr@file + # traefik.http.routers.-more.middlewares: lan-only@file # traefik.http.routers.-more.tls: true # traefik.http.routers.-more.tls.certresolver: myresolver \ No newline at end of file diff --git a/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.bobo b/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.bobo new file mode 100644 index 0000000..2dd85be --- /dev/null +++ b/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.bobo @@ -0,0 +1,19 @@ +http: + middlewares: + authentik_sysmgr: + forwardAuth: + address: https://auth.avital14.com/outpost.goauthentik.io/auth/traefik + trustForwardHeader: true + authResponseHeadersRegex: "^[Xx]-[Aa]uthentik" + # authResponseHeaders: + # - X-authentik-username + # - X-authentik-groups + # - X-authentik-email + # - X-authentik-name + # - X-authentik-uid + # - X-authentik-jwt + # - X-authentik-meta-jwks + # - X-authentik-meta-outpost + # - X-authentik-meta-provider + # - X-authentik-meta-app + # - X-authentik-meta-version diff --git a/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.sz b/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.sz new file mode 100644 index 0000000..9c7dbfb --- /dev/null +++ b/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.sz @@ -0,0 +1,19 @@ +http: + middlewares: + authentik_sysmgr: + forwardAuth: + address: https://auth.szk.li/outpost.goauthentik.io/auth/traefik + trustForwardHeader: true + authResponseHeadersRegex: "^[Xx]-[Aa]uthentik" + # authResponseHeaders: + # - X-authentik-username + # - X-authentik-groups + # - X-authentik-email + # - X-authentik-name + # - X-authentik-uid + # - X-authentik-jwt + # - X-authentik-meta-jwks + # - X-authentik-meta-outpost + # - X-authentik-meta-provider + # - X-authentik-meta-app + # - X-authentik-meta-version \ No newline at end of file diff --git a/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.wolfpack b/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.wolfpack new file mode 100644 index 0000000..c2a0f57 --- /dev/null +++ b/_traefik/dynamic/_templates/mw.fwd-auth-sysmgr.yml.wolfpack @@ -0,0 +1,19 @@ +http: + middlewares: + authentik_sysmgr: + forwardAuth: + address: https://auth.shefet.net/outpost.goauthentik.io/auth/traefik + trustForwardHeader: true + authResponseHeadersRegex: "^[Xx]-[Aa]uthentik" + # authResponseHeaders: + # - X-authentik-username + # - X-authentik-groups + # - X-authentik-email + # - X-authentik-name + # - X-authentik-uid + # - X-authentik-jwt + # - X-authentik-meta-jwks + # - X-authentik-meta-outpost + # - X-authentik-meta-provider + # - X-authentik-meta-app + # - X-authentik-meta-version \ No newline at end of file diff --git a/_traefik/dynamic/_templates/rt.dockge.yml.bobo b/_traefik/dynamic/_templates/rt.dockge.yml.bobo new file mode 100644 index 0000000..7a9eaba --- /dev/null +++ b/_traefik/dynamic/_templates/rt.dockge.yml.bobo @@ -0,0 +1,23 @@ +# http routing section +http: + routers: + # Define a connection between requests and services + home-assistant: + rule: "Host(`dockge.toronto.avital14.com`)" + entrypoints: + - websecure + # # If the rule matches, applies the middleware + # middlewares: + # - test-user + # If the rule matches, forward to the whoami service (declared below) + service: home-assistant + tls: + certresolver: myresolver + + services: + # Define how to reach an existing service on our infrastructure + home-assistant: + loadBalancer: + servers: + - url: "http://dockge:31014" + #- address: "ha.lan:8123" diff --git a/_copy_to_traefik/dynamic/ha.yml b/_traefik/dynamic/_templates/rt.ha.yml.sz similarity index 96% rename from _copy_to_traefik/dynamic/ha.yml rename to _traefik/dynamic/_templates/rt.ha.yml.sz index 82ad8e7..66ce575 100644 --- a/_copy_to_traefik/dynamic/ha.yml +++ b/_traefik/dynamic/_templates/rt.ha.yml.sz @@ -2,7 +2,7 @@ http: routers: # Define a connection between requests and services - "to-ha": + home-assistant: rule: "Host(`ha.lksz.me`)" entrypoints: - websecure diff --git a/_traefik/dynamic/_templates/rt.ha.yml.wolfpack b/_traefik/dynamic/_templates/rt.ha.yml.wolfpack new file mode 100644 index 0000000..715c961 --- /dev/null +++ b/_traefik/dynamic/_templates/rt.ha.yml.wolfpack @@ -0,0 +1,24 @@ +# http routing section +http: + routers: + # Define a connection between requests and services + home-assistant: + rule: "Host(`ha.shefet.net`)" + entrypoints: + - websecure + # # If the rule matches, applies the middleware + # middlewares: + # - trustedHeaders + # If the rule matches, forward to the whoami service (declared below) + service: home-assistant + tls: + certresolver: myresolver + + services: + # Define how to reach an existing service on our infrastructure + home-assistant: + loadBalancer: + servers: + - url: "http://ha.lan:8123" + #- address: "ha.lan:8123" + diff --git a/_traefik/dynamic/http.yml b/_traefik/dynamic/http.yml new file mode 100644 index 0000000..ef2bee2 --- /dev/null +++ b/_traefik/dynamic/http.yml @@ -0,0 +1,4 @@ +http: + serversTransports: + insecuretransport: + insecureSkipVerify: true diff --git a/_traefik/dynamic/mw.lan-only.yml b/_traefik/dynamic/mw.lan-only.yml new file mode 100644 index 0000000..2117f6d --- /dev/null +++ b/_traefik/dynamic/mw.lan-only.yml @@ -0,0 +1,9 @@ +# Accepts request from defined IP +http: + middlewares: + lan-only: + ipWhiteList: + sourceRange: + - "127.0.0.1/32" + - "192.168.0.0/16" + diff --git a/_copy_to_traefik/dynamic/dynamic.yml b/_traefik/dynamic/mw.secureHeaders.yml similarity index 63% rename from _copy_to_traefik/dynamic/dynamic.yml rename to _traefik/dynamic/mw.secureHeaders.yml index 1d02dc6..3ca24bc 100644 --- a/_copy_to_traefik/dynamic/dynamic.yml +++ b/_traefik/dynamic/mw.secureHeaders.yml @@ -1,7 +1,4 @@ http: - serversTransports: - insecuretransport: - insecureSkipVerify: true middlewares: secureHeaders: headers: @@ -17,14 +14,3 @@ http: permissionsPolicy: "camera=(), microphone=(), geolocation=()" customResponseHeaders: X-Robots-Tag: "noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex" - -tls: - stores: - default: - defaultCertificate: - certFile: /etc/traefik/tls/cert.pem - keyFile: /etc/traefik/tls/key.pem - certificates: - - certFile: /etc/traefik/tls/cert.pem - keyFile: /etc/traefik/tls/key.pem - diff --git a/_traefik/dynamic/tls.yml b/_traefik/dynamic/tls.yml new file mode 100644 index 0000000..39b4586 --- /dev/null +++ b/_traefik/dynamic/tls.yml @@ -0,0 +1,9 @@ +tls: + stores: + default: + defaultCertificate: + certFile: /etc/traefik/tls/cert.pem + keyFile: /etc/traefik/tls/key.pem + certificates: + - certFile: /etc/traefik/tls/cert.pem + keyFile: /etc/traefik/tls/key.pem diff --git a/_traefik/static.full.yml b/_traefik/static.full.yml new file mode 100644 index 0000000..283ebb9 --- /dev/null +++ b/_traefik/static.full.yml @@ -0,0 +1,60 @@ + # log: + # level: INFO + + api: + dashboard: true + insecure: true + + providers: + docker: + endpoint: "unix:///var/run/docker.sock" + watch: true + exposedByDefault: false + file: + directory: /srv/traefik/dynamic + watch: true + + entryPoints: + plex: + address: ':32400' + forwardedHeaders: + trustedIPs: + - "127.0.0.1/32" + - "172.16.0.0/12" + http: + redirections: + entryPoint: + to: 'websecure' + scheme: 'https' + + web: + address: ':80' + forwardedHeaders: + trustedIPs: + - "127.0.0.1/32" + - "172.16.0.0/12" + http: + redirections: + entryPoint: + to: 'websecure' + scheme: 'https' + websecure: + address: ':443' + forwardedHeaders: + trustedIPs: + - "127.0.0.1/32" + - "172.16.0.0/12" + + certificatesResolvers: + myresolver: + acme: + # email: acme@thisprops.com + storage: /shared/acme.json + # httpChallenge: + # entryPoint: web + #logging: true + dnsChallenge: + provider: cloudflare + resolvers: + - 1.1.1.1:53 # - --certificatesresolvers.cloudflare.acme.dnschallenge.resolvers[0]=1.1.1.1:53 + - 8.8.8.8:53 # - --certificatesresolvers.cloudflare.acme.dnschallenge.resolvers[1]=8.8.8.8:53 \ No newline at end of file diff --git a/_traefik/static.httponly.yml b/_traefik/static.httponly.yml new file mode 100644 index 0000000..8b6a9f2 --- /dev/null +++ b/_traefik/static.httponly.yml @@ -0,0 +1,32 @@ + # log: + # level: INFO + + api: + dashboard: true + insecure: true + + providers: + docker: + endpoint: "unix:///var/run/docker.sock" + watch: true + exposedByDefault: false + file: + directory: /srv/traefik/dynamic + watch: true + + entryPoints: + web: + address: ':88' + forwardedHeaders: + trustedIPs: + - "127.0.0.1/32" + - "172.16.0.0/12" + websecure: + address: ':8443' + forwardedHeaders: + trustedIPs: + - "127.0.0.1/32" + - "172.16.0.0/12" + + certificatesResolvers: + myresolver: diff --git a/authentik/docker-compose.yml b/authentik/docker-compose.yml index 20ca084..6f29918 100644 --- a/authentik/docker-compose.yml +++ b/authentik/docker-compose.yml @@ -4,3 +4,5 @@ services: - type: bind source: ${ROOT_FOLDER_HOST}/user-config/${APP_ID}/media target: /media + labels: + traefik.http.routers.authentik.rule: Host(`auth.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} diff --git a/code-server/docker-compose.yml b/code-server/docker-compose.yml index 3b55b68..3ac012b 100644 --- a/code-server/docker-compose.yml +++ b/code-server/docker-compose.yml @@ -1,8 +1,8 @@ services: code-server: environment: - PUID: "${SZ_USER_UID}" - PGID: "${SZ_USER_GID}" + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" volumes: - /var/run/docker.sock:/var/run/docker.sock - /:/mnt/runtipi.host diff --git a/code-server/wrokspace.code-workspace b/code-server/wrokspace.code-workspace index cef6485..2b97e4e 100644 --- a/code-server/wrokspace.code-workspace +++ b/code-server/wrokspace.code-workspace @@ -1,13 +1,10 @@ { "folders": [ - { - "path": "../../../dockge/stacks" - }, { "path": ".." }, { - "path": "../.." + "path": "../../.." } ], "settings": {} diff --git a/ddns-updater/docker-compose.yml b/ddns-updater/docker-compose.yml new file mode 100644 index 0000000..77890ba --- /dev/null +++ b/ddns-updater/docker-compose.yml @@ -0,0 +1,57 @@ +services: + ddns-updater: + dns: + - 1.1.1.1 + environment: + USER_UID: "${HOST_UID:?Must specify HOST_UID}" + USER_GID: "${HOST_GID:-${HOST_UID}}" + + ### Configuration + # DATADIR: "/updater/data" + # CONFIG_FILEPATH: "/updater/data/config.json" + # CONFIG: "" + # PERIOD: "5m" + + # UPDATE_COOLDOWN_PERIOD: "5m" + # PUBLICIP_FETCHERS: "all" + # PUBLICIP_HTTP_PROVIDERS: "all" + # PUBLICIPV4_HTTP_PROVIDERS: "all" + # PUBLICIPV6_HTTP_PROVIDERS: "all" + # PUBLICIP_DNS_PROVIDERS: "all" + # PUBLICIP_DNS_TIMEOUT: "3s" + # HTTP_TIMEOUT: "10s" + + # RESOLVER_ADDRESS: "" + # RESOLVER_TIMEOUT: "5s" + + ### Web UI + # SERVER_ENABLED: "yes" + # LISTENING_ADDRESS: ":8000" + # ROOT_URL: "/" + + ### Backup + # BACKUP_PERIOD: "0" + # BACKUP_DIRECTORY: "/updater/data" + + ### Other + # LOG_LEVEL: "info" + # LOG_CALLER: "hidden" + + ### SHOUTRRR + # SHOUTRRR_ADDRESSES: "" + # SHOUTRRR_DEFAULT_TITLE: "DDNS Updater" + + ### Health Check + # HEALTH_SERVER_ADDRESS: "127.0.0.1:9999" + # HEALTH_HEALTHCHECKSIO_BASE_URL: "https://hc-ping.com" + # HEALTH_HEALTHCHECKSIO_UUID: "" + labels: + traefik.http.routers.ddns-updater.rule: Host(`ddns.${ROOT_DOMAIN}`) + traefik.http.routers.ddns-updater.middlewares: authentik_sysmgr@file + + volumes: + #- dummy:/updater/data:ro + - type: bind + source: ${ROOT_FOLDER_HOST}/user-config/${APP_ID}/config.json + target: /updater/data/config.json + read_only: true diff --git a/ddns-updater/local.app.env b/ddns-updater/local.app.env new file mode 100644 index 0000000..51a60a7 --- /dev/null +++ b/ddns-updater/local.app.env @@ -0,0 +1,2 @@ +HOST_UID= +HOST_GID= diff --git a/dockge/docker-compose.yml b/dockge/docker-compose.yml index 467fa30..29831af 100644 --- a/dockge/docker-compose.yml +++ b/dockge/docker-compose.yml @@ -5,13 +5,28 @@ services: - /srv/dockge/stacks:/srv/dockge/stacks environment: DOCKGE_STACKS_DIR: /srv/dockge/stacks + + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + HOST_UID: "${HOST_UID}" + HOST_GID: "${HOST_GID}" + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + TZ: "${TZ:?Did you forget to define TZ in the root RunTipi .env.local?}" labels: - traefik.enable: true - # traefik.http.services.dockge.loadbalancer.server.port: 5001 - traefik.http.routers.dockge.entrypoints: websecure - traefik.http.routers.dockge.rule: Host(`${APP_DOMAIN}`) - traefik.http.routers.dockge.service: dockge + traefik.http.routers.dockge.rule: Host(`dockge.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} traefik.http.routers.dockge.middlewares: authentik_sysmgr@file - traefik.http.routers.dockge.tls.certresolver: myresolver - \ No newline at end of file + # traefik.enable: true + # # traefik.http.services.dockge.loadbalancer.server.port: 5001 + # traefik.http.routers.dockge.entrypoints: websecure + # traefik.http.routers.dockge.service: dockge + # traefik.http.routers.dockge.tls.certresolver: myresolver diff --git a/dozzle/docker-compose.yml b/dozzle/docker-compose.yml new file mode 100644 index 0000000..d595ab7 --- /dev/null +++ b/dozzle/docker-compose.yml @@ -0,0 +1,34 @@ +services: + dozzle: + hostname: dozzle.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + # volumes_from: + # - "container:vols-dl" + # - "container:vols-personal-media" + # - "container:vols-shared-media" + # - "container:vols-media" + # - "container:vols-arr" + # - "container:vols-plex" + labels: + # Websecure + traefik.http.routers.dozzle.middlewares: authentik_sysmgr@file + # traefik.http.routers.dozzle.middlewares: lan-only@file + # traefik.http.routers.dozzle-more.rule: Host(`dozzle.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} + # traefik.http.routers.dozzle-more.entrypoints: websecure + # traefik.http.routers.dozzle-more.service: dozzle + # traefik.http.routers.dozzle-more.middlewares: authentik_sysmgr@file + # traefik.http.routers.dozzle-more.middlewares: lan-only@file + # traefik.http.routers.dozzle-more.tls: true + # traefik.http.routers.dozzle-more.tls.certresolver: myresolver \ No newline at end of file diff --git a/forgejo/docker-compose.yml b/forgejo/docker-compose.yml new file mode 100644 index 0000000..c1bab74 --- /dev/null +++ b/forgejo/docker-compose.yml @@ -0,0 +1,19 @@ +services: + forgejo: + environment: + USER_UID: "${HOST_UID}" + USER_GID: "${HOST_GID}" + + FORGEJO__server__DOMAIN: "code.${ALT_ROOT_DOMAIN}" + FORGEJO__server__ROOT_URL: "https://code.${ALT_ROOT_DOMAIN}" + FORGEJO__server__SSH_DOMAIN: "code.${ALT_ROOT_DOMAIN}" + FORGEJO__service__ENABLE_CAPTCHA: "true" + FORGEJO__service__REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA: "true" + FORGEJO__service__DEFAULT_KEEP_EMAIL_PRIVATE: "true" + FORGEJO__service__DEFAULT_USER_IS_RESTRICTED: "true" + FORGEJO__service__ALLOW_ONLY_EXTERNAL_REGISTRATION: "true" + FORGEJO__service_explore__DISABLE_USERS_PAGE: "true" + + labels: + # Websecure + traefik.http.routers.forgejo.rule: Host(`code.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} diff --git a/homepage/docker-compose.yml b/homepage/docker-compose.yml new file mode 100644 index 0000000..c447da1 --- /dev/null +++ b/homepage/docker-compose.yml @@ -0,0 +1,25 @@ +services: + homepage: + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + + labels: + # Websecure + traefik.http.routers.homepage.middlewares: authentik_sysmgr@file + traefik.http.routers.homepage.rule: Host(`www.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} + # #traefik.http.routers.homepage-more.rule: Host(`www.${ALT_ROOT_DOMAIN}`) + # traefik.http.routers.homepage-more.entrypoints: websecure + # traefik.http.routers.homepage-more.service: homepage + # traefik.http.routers.homepage-more.middlewares: authentik_sysmgr@file + # traefik.http.routers.homepage-more.tls.certresolver: myresolver \ No newline at end of file diff --git a/jellyseerr/docker-compose.yml b/jellyseerr/docker-compose.yml new file mode 100644 index 0000000..8688966 --- /dev/null +++ b/jellyseerr/docker-compose.yml @@ -0,0 +1,19 @@ +services: + jellyseerr: + hostname: jellyseerr.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + labels: + # Websecure + traefik.http.routers.jellyseerr.rule: Host(`req.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} \ No newline at end of file diff --git a/plex/docker-compose.yml b/plex/docker-compose.yml index 3e2af33..68d6a9e 100644 --- a/plex/docker-compose.yml +++ b/plex/docker-compose.yml @@ -1,81 +1,9 @@ services: plex: - network_mode: "" #container:plexnet - networks: - lan: - ipv4_address: 192.168.222.46 environment: - PUID: "${SZ_USER_UID}" - PGID: "${SZ_USER_GID}" - volumes: - # dummy.config is used to preserve /config permissions only, this prevents the recursive chown from running on startup - - /srv/plex/dummy.config:/config - # Actual plex/config dataset - - /srv/plex/config:/config/Library/Application Support/Plex Media Server - # Actual plex/transcode dataset - - /srv/plex/transcode:/transcode - - # NFS mounts - - media1video:/media/1/video - - media0:/media/0 - - media0personal:/media/0.personal - - #- ${APP_DATA_DIR}/data/config:/config - - # Throwaway volumes: - - cache_root:/config/Library/Application Support/Plex Media Server/Cache - # - crash_reports:/config/Library/Application Support/Plex Media Server/Crash Reports - # - cache_Metadata:/config/Library/Application Support/Plex Media Server/Metadata/Cache - # - cache_Metadata_PlugInSupport:/config/Library/Application Support/Plex Media Server/Metadata/Plug-in Support/Cache - # - /srv/plex/transcode:/config/Library/Application Support/Plex Media Server/Transcode - -volumes: - media1: - external: true -# driver_opts: -# type: nfs -# o: addr=kateryna.lan,nolock,soft,rw -# device: :/mnt/szusb1/z/media - media1video: - external: true -# driver_opts: -# type: nfs -# o: addr=kateryna.lan,nolock,soft,rw -# device: :/mnt/szusb1/z/media/video - media0personal: - external: true -# driver_opts: -# type: nfs -# o: addr=kateryna.lan,nolock,soft,rw -# device: :/mnt/szmedia/media.personal - media0: - external: true -# driver_opts: -# type: nfs -# o: addr=kateryna.lan,nolock,soft,rw -# device: :/mnt/szmedia/media - cache_root: - external: true - name: plex_cache_root - crash_reports: - external: true - name: plex_crash_reports - cache_Metadata: - external: true - name: plex_cache_Metadata - cache_Metadata_PlugInSupport: - external: true - name: plex_cache_Metadata_PlugInSupport - -networks: - lan: - external: true -# driver: ipvlan -# ipam: -# config: -# - subnet: ${MY_SUBNET} -# gateway: ${MY_IPv4_GW} -# # - subnet: 192.168.1.0/24 -# driver_opts: -# com.docker.network.enable_ipv6: "false" -# parent: ${MY_NET_IF} \ No newline at end of file + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + network_mode: "container:net-plex" + #networks: [] + volumes_from: + - "container:vols-plex" \ No newline at end of file diff --git a/prowlarr/docker-compose.yml b/prowlarr/docker-compose.yml new file mode 100644 index 0000000..c192ff8 --- /dev/null +++ b/prowlarr/docker-compose.yml @@ -0,0 +1,27 @@ +services: + prowlarr: + hostname: prowlarr.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + labels: + # Websecure + traefik.http.routers.prowlarr.middlewares: authentik_sysmgr@file + # traefik.http.routers.prowlarr.middlewares: lan-only@file + traefik.http.routers.prowlarr.rule: Host(`prowlarr.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} + # traefik.http.routers.prowlarr-more.entrypoints: websecure + # traefik.http.routers.prowlarr-more.service: prowlarr + # traefik.http.routers.prowlarr-more.middlewares: authentik_sysmgr@file + # traefik.http.routers.prowlarr-more.middlewares: lan-only@file + # traefik.http.routers.prowlarr-more.tls: true + # traefik.http.routers.prowlarr-more.tls.certresolver: myresolver \ No newline at end of file diff --git a/radarr/docker-compose.yml b/radarr/docker-compose.yml new file mode 100644 index 0000000..cc69990 --- /dev/null +++ b/radarr/docker-compose.yml @@ -0,0 +1,29 @@ +services: + radarr: + hostname: radarr.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + volumes_from: + - "container:vols-arr" + labels: + # Websecure + traefik.http.routers.radarr.middlewares: authentik_sysmgr@file + # traefik.http.routers.radarr.middlewares: lan-only@file + # traefik.http.routers.radarr-more.rule: Host(`radarr.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} + # traefik.http.routers.radarr-more.entrypoints: websecure + # traefik.http.routers.radarr-more.service: radarr + # traefik.http.routers.radarr-more.middlewares: authentik_sysmgr@file + # traefik.http.routers.radarr-more.middlewares: lan-only@file + # traefik.http.routers.radarr-more.tls: true + # traefik.http.routers.radarr-more.tls.certresolver: myresolver \ No newline at end of file diff --git a/sabnzbd/docker-compose.yml b/sabnzbd/docker-compose.yml new file mode 100644 index 0000000..39a8ec3 --- /dev/null +++ b/sabnzbd/docker-compose.yml @@ -0,0 +1,29 @@ +services: + sabnzbd: + hostname: nzb.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + volumes_from: + - "container:vols-dl" + labels: + # Websecure + traefik.http.routers.sabnzbd.middlewares: authentik_sysmgr@file + # traefik.http.routers.sabnzbd.middlewares: lan-only@file + traefik.http.routers.sabnzbd.rule: Host(`nzb.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} + # traefik.http.routers.sabnzbd-more.entrypoints: websecure + # traefik.http.routers.sabnzbd-more.service: sabnzbd + # traefik.http.routers.sabnzbd-more.middlewares: authentik_sysmgr@file + # traefik.http.routers.sabnzbd-more.middlewares: lan-only@file + # traefik.http.routers.sabnzbd-more.tls: true + # traefik.http.routers.sabnzbd-more.tls.certresolver: myresolver \ No newline at end of file diff --git a/sonarr/docker-compose.yml b/sonarr/docker-compose.yml new file mode 100644 index 0000000..8438170 --- /dev/null +++ b/sonarr/docker-compose.yml @@ -0,0 +1,29 @@ +services: + sonarr: + hostname: sonarr.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + volumes_from: + - "container:vols-arr" + labels: + # Websecure + traefik.http.routers.sonarr.middlewares: authentik_sysmgr@file + # traefik.http.routers.sonarr.middlewares: lan-only@file + traefik.http.routers.sonarr-more.rule: Host(`sonarr.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} + # traefik.http.routers.sonarr-more.entrypoints: websecure + # traefik.http.routers.sonarr-more.service: sonarr + # traefik.http.routers.sonarr-more.middlewares: authentik_sysmgr@file + # traefik.http.routers.sonarr-more.middlewares: lan-only@file + # traefik.http.routers.sonarr-more.tls: true + # traefik.http.routers.sonarr-more.tls.certresolver: myresolver \ No newline at end of file diff --git a/syncthing/docker-compose.yml b/syncthing/docker-compose.yml new file mode 100644 index 0000000..b372058 --- /dev/null +++ b/syncthing/docker-compose.yml @@ -0,0 +1,24 @@ +services: + syncthing: + hostname: syncthing.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + volumes_from: + - "container:vols-all" + volumes: + - "/mnt/szmedia/sync.root:/mnt/szmedia/sync.root" + labels: + # Websecure + traefik.http.routers.syncthing.middlewares: authentik_sysmgr@file + traefik.http.routers.syncthing.rule: Host(`sync.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} \ No newline at end of file diff --git a/szetup.sh b/szetup.sh new file mode 100755 index 0000000..65f099b --- /dev/null +++ b/szetup.sh @@ -0,0 +1,81 @@ +#! /usr/bin/env bash +set -e +SCRIPT_DIR=${SCRIPT_DIR:-"$( cd -- "$( dirname -- "$0" )" &> /dev/null && pwd )"} + +SYS_NAME=${1:-${SYS_NAME:?Must supply sysname as 1st argument}} +TOP_DIR="$SCRIPT_DIR/_traefik/dynamic" + +# Store the find results in an array +mapfile -d '' -t DELETE < <(find "$TOP_DIR" -maxdepth 1 -mindepth 1 -type l -lname '*_templates/*' -print0) + +# If links were found, process and delete them +if [ ${#DELETE[@]} -gt 0 ]; then + for link in "${DELETE[@]}"; do + # Get the target of the symbolic link + target=$(basename $(readlink -f "$link")) + + # Delete the link + rm "$link" + + # Report the deleted link and its target + printf '"%s" (%s) deleted.\n' "$link" "${target##*.}" + done +else + echo "No matching symbolic links found to delete." +fi + +find "$TOP_DIR/_templates" -maxdepth 1 -mindepth 1 -type f -name "*.${SYS_NAME}" -print0 \ +| while IFS= read -r -d '' file; do + base=$(basename "$file" ".${SYS_NAME}") + ext="${base##*.}" + #echo ln -rs "${file#${TOP_DIR}/}" "${base}" + ln -vrs "${file}" "${TOP_DIR}/${base%${ext}}local.$ext" +done + +SECRET_BASE="${SCRIPT_DIR}/_secrets" +SECRETS=( + "tipi_jwt_secret" + "tipi_postgres_password" + "tipi_redis_password" +) +for file in "${SECRETS[@]}"; do + secret="${SECRET_BASE}/${file}.txt" + printf '%s secret ' "${file}" + if [ -s "${secret}" ]; then + printf 'exists.' + else + printf 'generating... ' + curl -s "https://makemeapassword.ligos.net/api/v1/passphrase/plain?pc=1&wc=6&sp=y&maxCh=64" \ + | sed -Ee 's/ /-/g;' > "${secret}" + printf 'ready.' + fi + printf '\n' +done + +SECRETS=( + "traefik_cf_dns_api_token" +) +for file in "${SECRETS[@]}"; do + secret="${SECRET_BASE}/${file}.txt" + printf '%s secret ' "${file}" + if [ -s "${secret}" ]; then + printf 'exists.' + else + printf 'missing!' + fi + printf '\n' +done + +if [ -r "${SCRIPT_DIR}/.env.local.${SYS_NAME}.dotenv" ]; then + [ -L "${SCRIPT_DIR}/.env.local" ] && rm "${SCRIPT_DIR}/.env.local" + ln -srv "${SCRIPT_DIR}/.env.local.${SYS_NAME}.dotenv" "${SCRIPT_DIR}/.env.local" +fi + +if [ "$2" == "--setup" ]; then + "${SCRIPT_DIR}/_bin/rtpctl.d" setup "-vf" + "${SCRIPT_DIR}/_bin/rtpctl.d" setup "-vf" $HOME/.local/bin/rtpctl + "${SCRIPT_DIR}/_bin/rtpctl.d" setup "-vf" $HOME/.local/bin/runtipictl + "${SCRIPT_DIR}/_bin/rtpctl.d" setup "-vf" $HOME/.local/bin/tpc +fi + +# vim: set ft=sh expandtab tabstop=4 shiftwidth=4: diff --git a/tautulli/docker-compose.yml b/tautulli/docker-compose.yml new file mode 100644 index 0000000..337545b --- /dev/null +++ b/tautulli/docker-compose.yml @@ -0,0 +1,20 @@ +services: + tautulli: + hostname: tautulli.docker + environment: + PUID: "${HOST_UID}" + PGID: "${HOST_GID}" + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED:-}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + RUNTIPI_LOCAL_DOMAIN: "${LOCAL_DOMAIN}" + RUNTIPI_DOMAIN: "${DOMAIN}" + RUNTIPI_ROOT_DOMAIN: "${ROOT_DOMAIN}" + labels: + # Websecure + traefik.http.routers.tautulli.middlewares: authentik_sysmgr@file + # traefik.http.routers.tautulli-more.rule: Host(`tautulli.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} diff --git a/tipi-compose.yml b/tipi-compose.yml old mode 100755 new mode 100644 index 944273a..9f16d30 --- a/tipi-compose.yml +++ b/tipi-compose.yml @@ -1,14 +1,77 @@ +secrets: +# tipi_jwt_secret: +# file: ${RUNTIPI_ROOT_FOLDER_HOST}/user-config/_secrets/tipi_jwt_secret.txt +# # JWT_SECRET: /run/secrets/tipi_jwt_secret +# tipi_postgres_password: +# file: ${RUNTIPI_ROOT_FOLDER_HOST}/user-config/_secrets/tipi_postgres_password.txt +# # POSTGRES_PASSWORD: /run/secrets/tipi_postgres_password +# tipi_redis_password: +# file: ${RUNTIPI_ROOT_FOLDER_HOST}/user-config/_secrets/tipi_redis_password.txt +# # REDIS_PASSWORD: /run/secrets/tipi_redis_password + traefik_cf_dns_api_token: + file: ${RUNTIPI_ROOT_FOLDER_HOST}/user-config/_secrets/traefik_cf_dns_api_token.txt services: runtipi-reverse-proxy: + secrets: + - traefik_cf_dns_api_token + volumes: + - type: bind + source: ./traefik/shared + target: /shared + read_only: false + - type: bind + source: ./traefik + target: /srv/traefik + read_only: false + - type: bind + source: ./user-config/_traefik/dynamic/ + target: /srv/traefik/dynamic/ + read_only: true + - type: bind + source: ./user-config/_traefik/static.${TRAEFIK_STATIC:-full}.yml + target: /srv/traefik/static.yml + read_only: true + logging: + driver: "json-file" + options: + max-size: "2m" + max-file: "3" ports: - 8080:8080 - command: - - '--providers.docker' - - '--providers.file.directory=/srv/runtipi/traefik/dynamic' + - 80:80 + - 443:443 + command: + - '--log.level=DEBUG' + - '--configFile=/srv/traefik/static.yml' - '--certificatesresolvers.myresolver.acme.email=${ACME_EMAIL}' - - '--certificatesresolvers.myresolver.acme.storage=/shared/acme.json' - - '--certificatesresolvers.myresolver.acme.dnshallenge.entrypoint=cloudflare' environment: - CF_API_EMAIL: "${ACME_EMAIL}" - CF_DNS_API_TOKEN: "${CF_DNS_API_TOKEN}" + CF_API_EMAIL: "${ACME_EMAIL:?}" + CF_DNS_API_TOKEN_FILE: /run/secrets/traefik_cf_dns_api_token + TRAEFIK_API_DISABLEDASHBOARDAD: "true" + networks: + - tipi_main_network + - tipi_internal_network + - ix-dozzle +networks: + tipi_main_network: + attachable: true + name: runtipi_tipi_main_network + driver: bridge + driver_opts: + com.docker.network.bridge.name: "tipi-br1" + tipi_internal_network: + internal: true + attachable: true + name: runtipi_tipi_internal_network + driver: bridge + driver_opts: + com.docker.network.bridge.name: "tipi-br0" + ix-dozzle: + external: true + name: ix-dozzle_default +# ix-dockge: +# external: true +# name: ix-dockge_default + +# vim: set ft=yaml expandtab tabstop=2 shiftwidth=2: diff --git a/uptime-kuma/docker-compose.yml b/uptime-kuma/docker-compose.yml new file mode 100644 index 0000000..e1b1952 --- /dev/null +++ b/uptime-kuma/docker-compose.yml @@ -0,0 +1,18 @@ +services: + uptime-kuma: + hostname: uptime-kuma + environment: + # RUNTIPI Environment + RUNTIPI_APP_PORT: "${APP_PORT}" + RUNTIPI_APP_ID: "${APP_ID}" + RUNTIPI_APP_DATA_DIR: "${APP_DATA_DIR}" + RUNTIPI_APP_EXPOSED: "${APP_EXPOSED}" + RUNTIPI_APP_DOMAIN: "${APP_DOMAIN}" + RUNTIPI_APP_HOST: "${APP_HOST}" + # labels: + # # Websecure + # traefik.http.routers.uptime-kuma-more.rule: Host(`vault.lksz.me`)${APP_ROUTE_OPTIONAL:-} + # traefik.http.routers.uptime-kuma-more.entrypoints: websecure + # traefik.http.routers.uptime-kuma-more.service: uptime-kuma + # traefik.http.routers.uptime-kuma-more.tls: true + # traefik.http.routers.uptime-kuma-more.tls.certresolver: myresolver diff --git a/vaultwarden/docker-compose.yml b/vaultwarden/docker-compose.yml index 514225a..b1f4e2b 100644 --- a/vaultwarden/docker-compose.yml +++ b/vaultwarden/docker-compose.yml @@ -12,17 +12,15 @@ services: RUNTIPI_APP_HOST: "${APP_HOST}" networks: # - tipi_main_network - - vaultwarden_pg_dockge + - vaultwarden-pg + volumes: + - ../vaultwarden/data:/data labels: - # Main - traefik.docker.network: runtipi_tipi_main_network - # # Websecure - traefik.http.routers.vaultwarden-more.rule: Host(`vault.lksz.me`)${APP_ROUTE_OPTIONAL:-} - traefik.http.routers.vaultwarden-more.entrypoints: websecure - traefik.http.routers.vaultwarden-more.service: vaultwarden - traefik.http.routers.vaultwarden-more.tls: true - traefik.http.routers.vaultwarden-more.tls.certresolver: myresolver + # Websecure + traefik.http.routers.vaultwarden.rule: Host(`vault.${ROOT_DOMAIN}`)${APP_ROUTE_OPTIONAL:-} + traefik.docker.network: tipi_main_network #runtipi_tipi_main_network networks: - vaultwarden_pg_dockge: + vaultwarden-pg: external: true - name: vaultwarden-pg_dockge + name: vault_pg_net +