Compare commits

..

14 Commits

Author SHA1 Message Date
daniel156161 1445be23a0 mv TMP_FILE to borg_exporter.prom and only pars data that got fully written
Build and Push Docker Container / build-and-push (push) Successful in 1m8s
2026-05-02 11:18:08 +02:00
daniel156161 317e8b6b16 fix node exporter to keep last data
Build and Push Docker Container / build-and-push (push) Successful in 1m37s
2026-05-01 16:34:09 +02:00
daniel156161 338ca43328 fix environment file to not fill with duplicate values with restart container
Build and Push Docker Container / build-and-push (push) Successful in 58s
2026-04-17 16:21:51 +02:00
daniel156161 441d9a9890 update container version
Build and Push Docker Container / build-and-push (push) Successful in 1m4s
2026-04-17 11:48:15 +02:00
daniel156161 df3ac965b9 fixing terminal sepurator to fill it
Build and Push Docker Container / build-and-push (push) Successful in 56s
2026-04-17 10:26:13 +02:00
daniel156161 e61bcb7af4 fix that version is only once
Build and Push Docker Container / build-and-push (push) Successful in 55s
2026-04-17 10:11:26 +02:00
daniel156161 1a1c6cbfbe fix creting of docker client version
Build and Push Docker Container / build-and-push (push) Successful in 54s
2026-04-17 09:56:17 +02:00
daniel156161 29a072cabe fix setting of docker socket version and use it over ssh
Build and Push Docker Container / build-and-push (push) Successful in 53s
2026-04-17 09:42:04 +02:00
daniel156161 5e42200431 set docker socket api version for client
Build and Push Docker Container / build-and-push (push) Successful in 1m5s
2026-04-17 09:24:15 +02:00
daniel156161 c3b235e4ed fix creating of authorized_keys and give borg docker socket permissions
Build and Push Docker Container / build-and-push (push) Successful in 59s
2026-04-17 09:06:43 +02:00
daniel156161 0609c7fedc add docker-cli and set correct column lengh in terminal
Build and Push Docker Container / build-and-push (push) Successful in 1m8s
2026-04-17 08:40:33 +02:00
daniel156161 dc27d4ea69 install fastfetch and only show fastfetch when installed and fix update alias and building of spaceing
Build and Push Docker Container / build-and-push (push) Successful in 1m17s
2026-04-12 00:52:00 +02:00
daniel156161 04cd1a4ee3 fix borg_exporter datediff error becuase alpine not have it, changed to python
Build and Push Docker Container / build-and-push (push) Waiting to run
2026-04-12 00:43:19 +02:00
daniel156161 1da0105b61 fix creating if user already exists
Build and Push Docker Container / build-and-push (push) Successful in 2m18s
2026-04-12 00:04:10 +02:00
7 changed files with 117 additions and 43 deletions
+2 -2
View File
@@ -10,8 +10,8 @@ ENV RUN_PROMETHEUS_EXPORTER="false"
ENV TZ="" ENV TZ=""
RUN apk add --no-cache \ RUN apk add --no-cache \
bash sudo openssh-server shadow tzdata curl git dcron coreutils grep sed gawk util-linux ca-certificates tmux prometheus-node-exporter \ bash sudo openssh-server shadow tzdata curl git dcron coreutils grep sed gawk util-linux ca-certificates tmux fastfetch prometheus-node-exporter \
borgbackup \ borgbackup docker-cli \
&& mkdir -p \ && mkdir -p \
/.ssh \ /.ssh \
/backups \ /backups \
+11 -7
View File
@@ -1,9 +1,9 @@
if [ ! -z $(cat /etc/environment | grep "USE_TMUX_SHELL") ] && [[ -t 0 ]] && [ -z "$TMUX" ]; then if grep -q "USE_TMUX_SHELL" /etc/environment && [[ -t 0 ]] && [ -z "$TMUX" ]; then
tmux attach || tmux new-session tmux attach || tmux new-session
exit exit
fi fi
alias update='sudo pacman -Syu --noconfirm' alias update='sudo apk update && sudo apk upgrade'
export HISTTIMEFORMAT="%d/%m/%y %T " export HISTTIMEFORMAT="%d/%m/%y %T "
export PS1='\u@\h:\W \$ ' export PS1='\u@\h:\W \$ '
@@ -14,19 +14,23 @@ alias ll='ls -alF'
alias ls='ls --color=auto' alias ls='ls --color=auto'
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ " export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
############################################################################################################################## ###############################################################################
# Functions # Functions
############################################################################################################################## ###############################################################################
source "/variables.sh" source "/variables.sh"
COLUMNS=$(/usr/bin/tput cols) if command -v tput >/dev/null 2>&1; then
COLUMNS=$(tput cols)
fi
function print_container_info { function print_container_info {
sepurator sepurator
echo "BorgServer powered by $BORG_VERSION - Image Hostname: $HOSTNAME | Image Version: $DOCKER_IMAGE_VERSION" echo "BorgServer powered by $BORG_VERSION - Image Hostname: $HOSTNAME | Image Version: $DOCKER_IMAGE_VERSION"
sepurator sepurator
} }
############################################################################################################################## ###############################################################################
# Run Code # Run Code
############################################################################################################################## ###############################################################################
print_container_info print_container_info
if command -v fastfetch >/dev/null 2>&1; then
fastfetch --config neofetch fastfetch --config neofetch
fi
+10 -6
View File
@@ -1,4 +1,4 @@
alias update='pacman -Syu --noconfirm' alias update='apk update && apk upgrade'
export HISTTIMEFORMAT="%d/%m/%y %T " export HISTTIMEFORMAT="%d/%m/%y %T "
export PS1='\u@\h:\W \$ ' export PS1='\u@\h:\W \$ '
@@ -9,11 +9,13 @@ alias ll='ls -alF'
alias ls='ls --color=auto' alias ls='ls --color=auto'
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ " export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
############################################################################################################################## ###############################################################################
# Borg Repo finder # Borg Repo finder
############################################################################################################################## ###############################################################################
source "/variables.sh" source "/variables.sh"
COLUMNS=$(/usr/bin/tput cols) if command -v tput >/dev/null 2>&1; then
COLUMNS=$(tput cols)
fi
function find_borg_repo { function find_borg_repo {
repo_list=( $(find "$1" -name "index.*" -type f | rev | cut -d '/' -f "2-" | rev) ) repo_list=( $(find "$1" -name "index.*" -type f | rev | cut -d '/' -f "2-" | rev) )
@@ -84,9 +86,9 @@ function print_container_info {
echo "BorgServer powered by $BORG_VERSION - Image Hostname: $HOSTNAME | Image Version: $DOCKER_IMAGE_VERSION" echo "BorgServer powered by $BORG_VERSION - Image Hostname: $HOSTNAME | Image Version: $DOCKER_IMAGE_VERSION"
sepurator sepurator
} }
############################################################################################################################## ###############################################################################
# Run Code # Run Code
############################################################################################################################## ###############################################################################
if [ "$INTERACTIVE_MODE" != "false" ]; then if [ "$INTERACTIVE_MODE" != "false" ]; then
find_borg_repo /backups/ find_borg_repo /backups/
export BORG_REPO="${repo_list[selected_repo]}" export BORG_REPO="${repo_list[selected_repo]}"
@@ -97,4 +99,6 @@ if [ "$INTERACTIVE_MODE" != "false" ]; then
fi fi
print_container_info print_container_info
if command -v fastfetch >/dev/null 2>&1; then
fastfetch --config neofetch fastfetch --config neofetch
fi
+57 -7
View File
@@ -2,18 +2,19 @@
set -euo pipefail set -euo pipefail
source "/variables.sh" source "/variables.sh"
USER_GROUP="$USER"
############################################################################### ###############################################################################
# Funktionen # Funktionen
############################################################################### ###############################################################################
function set_environment_variables_if_not_empty { function set_environment_variables_if_not_empty {
# Set Tmux Shell for .bashrc to load tmux and attach session if exists else create new session # Set Tmux Shell for .bashrc to load tmux and attach session if exists else create new session
if [ -n "${USE_TMUX_SHELL:-}" ]; then if [ -n "${USE_TMUX_SHELL:-}" ]; then
echo "USE_TMUX_SHELL=$USE_TMUX_SHELL" >> /etc/environment grep -q "^USE_TMUX_SHELL=" /etc/environment || echo "USE_TMUX_SHELL=$USE_TMUX_SHELL" >> /etc/environment
fi fi
# Set Server Timezone # Set Server Timezone
if [ -n "${TZ:-}" ]; then if [ -n "${TZ:-}" ]; then
echo "TZ=$TZ" >> /etc/environment grep -q "^TZ=" /etc/environment || echo "TZ=$TZ" >> /etc/environment
ln -sf "/usr/share/zoneinfo/$TZ" /etc/localtime ln -sf "/usr/share/zoneinfo/$TZ" /etc/localtime
fi fi
} }
@@ -35,24 +36,72 @@ function create_folder_and_change_permissions {
if [ ! -d "$1" ]; then if [ ! -d "$1" ]; then
mkdir -p "$1" mkdir -p "$1"
fi fi
chown -R "$USER":"$USER" "$1" chown -R "$USER":"$USER_GROUP" "$1"
} }
function add_borg_user { function add_borg_user {
if ! id "$USER" >/dev/null 2>&1; then if ! id "$USER" >/dev/null 2>&1; then
local group_name="$USER"
local existing_group
existing_group="$(getent group "$GID" | cut -d: -f1 || true)"
if [ -n "$existing_group" ]; then
group_name="$existing_group"
elif ! getent group "$USER" >/dev/null 2>&1; then
groupadd -g "$GID" "$USER" >/dev/null groupadd -g "$GID" "$USER" >/dev/null
useradd -M -u "$UID" -g "$GID" -d / -s /bin/bash "$USER" >/dev/null fi
USER_GROUP="$group_name"
if getent passwd "$UID" >/dev/null 2>&1; then
existing_user="$(getent passwd "$UID" | cut -d: -f1)"
usermod -l "$USER" "$existing_user" >/dev/null 2>&1 || true
usermod -d / -s /bin/bash -g "$group_name" "$USER" >/dev/null
else
useradd -M -u "$UID" -g "$group_name" -d / -s /bin/bash "$USER" >/dev/null
fi
printf "%s ALL=(ALL) NOPASSWD: ALL\n" "$USER" >> /etc/sudoers printf "%s ALL=(ALL) NOPASSWD: ALL\n" "$USER" >> /etc/sudoers
create_folder_and_change_permissions "/.config" create_folder_and_change_permissions "/.config"
create_folder_and_change_permissions "/.cache" create_folder_and_change_permissions "/.cache"
chmod 700 "/.cache" chmod 700 "/.cache"
else
USER_GROUP="$(id -gn "$USER")"
fi fi
random_pw="$(dd if=/dev/urandom bs=18 count=1 2>/dev/null | base64)" random_pw="$(dd if=/dev/urandom bs=18 count=1 2>/dev/null | base64)"
echo "${USER}:${random_pw}" | chpasswd >/dev/null 2>&1 || true echo "${USER}:${random_pw}" | chpasswd >/dev/null 2>&1 || true
} }
function add_docker_socket_permission {
if [ ! -S /var/run/docker.sock ]; then
return
fi
local sock_gid
sock_gid="$(stat -c '%g' /var/run/docker.sock)"
local group_name
group_name="$(getent group "$sock_gid" | cut -d: -f1 || true)"
if [ -z "$group_name" ]; then
groupadd -g "$sock_gid" docker
group_name="docker"
fi
usermod -aG "$group_name" "$USER"
echo "* Docker socket access granted ($group_name GID=$sock_gid)"
local server_api
server_api="$(curl -sf --unix-socket /var/run/docker.sock http://localhost/version 2>/dev/null \
| grep -o '"ApiVersion":"[^"]*"' | head -1 | cut -d'"' -f4 | tr -d '[:space:]' || true)"
if [ -n "$server_api" ]; then
printf 'export DOCKER_API_VERSION="%s"\n' "$server_api" > /etc/profile.d/docker_api_version.sh
printf 'DOCKER_API_VERSION=%s\n' "$server_api" > "/.ssh/environment"
sed -i '/^DOCKER_API_VERSION=/d' /etc/environment
printf 'DOCKER_API_VERSION=%s\n' "$server_api" >> /etc/environment
export DOCKER_API_VERSION="$server_api"
echo "* Docker API version pinned to $server_api"
fi
}
function make_and_import_ssh_keys { function make_and_import_ssh_keys {
local create_folders="0" local create_folders="0"
@@ -76,12 +125,12 @@ function make_and_import_ssh_keys {
shopt -s nullglob shopt -s nullglob
for key in /sshkeys/clients/*; do for key in /sshkeys/clients/*; do
echo "- Adding SSH-Key $(basename "$key")" echo "- Adding SSH-Key $(basename "$key")"
cat "$key" >> "/.ssh/authorized_keys" awk 'NF' "$key" >> "/.ssh/authorized_keys"
echo "" >> "/.ssh/authorized_keys" printf '\n' >> "/.ssh/authorized_keys"
done done
shopt -u nullglob shopt -u nullglob
chown -R "$USER":"$USER" "/.ssh" chown -R "$USER":"$USER_GROUP" "/.ssh"
chmod 700 "/.ssh" chmod 700 "/.ssh"
chmod 600 "/.ssh/authorized_keys" chmod 600 "/.ssh/authorized_keys"
} }
@@ -189,6 +238,7 @@ function run_prometheus_exporter {
############################################################################### ###############################################################################
set_environment_variables_if_not_empty set_environment_variables_if_not_empty
add_borg_user add_borg_user
add_docker_socket_permission
print_container_info print_container_info
print_user_info print_user_info
+4 -3
View File
@@ -1,8 +1,8 @@
DOCKER_IMAGE_VERSION="3.0.0" DOCKER_IMAGE_VERSION="3.1.0"
BORG_VERSION=$(borg -V) BORG_VERSION=$(borg -V)
SSH_FOLDERS=( "/sshkeys/clients" "/sshkeys/host" ) SSH_FOLDERS=( "/sshkeys/clients" "/sshkeys/host" )
NODE_EXPORTER_DIR="/var/log" NODE_EXPORTER_DIR="/var/log"
COLUMNS="86" DEFAULT_COLUMNS="86"
############################################################################### ###############################################################################
# Funktionen # Funktionen
############################################################################### ###############################################################################
@@ -10,7 +10,8 @@ function sepurator {
if [ -n "${2:-}" ]; then if [ -n "${2:-}" ]; then
local end="$2" local end="$2"
else else
local end="$COLUMNS" local end
end=$(tput cols 2>/dev/null || echo "${COLUMNS:-${DEFAULT_COLUMNS:-80}}")
fi fi
local start=1 local start=1
+29 -15
View File
@@ -2,22 +2,17 @@
source /etc/borg_exporter.rc source /etc/borg_exporter.rc
source /variables.sh source /variables.sh
TMP_FILE="/tmp/prometheus-borg" TMP_FILE="/tmp/prometheus-borg.$$"
DATEDIFF=`which datediff`
if [ -z "$DATEDIFF" ]; then
#ubuntu packages have a different executable name
DATEDIFF=`which dateutils.ddiff`
fi
[ -e $TMP_FILE ] && rm -f $TMP_FILE [ -e "$TMP_FILE" ] && rm -f "$TMP_FILE"
#prevent "Attempting to access a previously unknown unencrypted repository" prompt #prevent "Attempting to access a previously unknown unencrypted repository" prompt
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
HOSTNAME=$(hostname) HOSTNAME=$(hostname)
############################################################################################################################## ###################################################################################################
# Funktionen # Funktionen
############################################################################################################################## ###################################################################################################
function writeToFile() { function writeToFile() {
msg="$1" msg="$1"
local -n arr=$2 local -n arr=$2
@@ -50,6 +45,20 @@ function calc_bytes {
esac esac
} }
function calc_hours_diff {
local start_ts="$1"
local end_ts="$2"
python3 - "$start_ts" "$end_ts" <<'PY'
from datetime import datetime
import sys
start = datetime.strptime(sys.argv[1], "%Y-%m-%d %H:%M:%S")
end = datetime.strptime(sys.argv[2], "%Y-%m-%d %H:%M:%S")
print(int((end - start).total_seconds() // 3600))
PY
}
function writeDefinitionsToMetrics() { function writeDefinitionsToMetrics() {
#print the definition of the metrics #print the definition of the metrics
echo "# HELP borg_hours_from_last_archive How many hours have passed since the last archive was added to the repo (counted by borg_exporter.sh)" >> $TMP_FILE echo "# HELP borg_hours_from_last_archive How many hours have passed since the last archive was added to the repo (counted by borg_exporter.sh)" >> $TMP_FILE
@@ -101,7 +110,7 @@ function getBorgDataForRepository {
if [ -n "${LAST_ARCHIVE}" ]; then if [ -n "${LAST_ARCHIVE}" ]; then
LAST_ARCHIVE_DATE=$(echo $LAST_ARCHIVE | awk '{print $3" "$4}') LAST_ARCHIVE_DATE=$(echo $LAST_ARCHIVE | awk '{print $3" "$4}')
CURRENT_DATE="$(date '+%Y-%m-%d %H:%M:%S')" CURRENT_DATE="$(date '+%Y-%m-%d %H:%M:%S')"
NB_HOUR_FROM_LAST_BCK=$($DATEDIFF "$LAST_ARCHIVE_DATE" "$CURRENT_DATE" -f '%H') NB_HOUR_FROM_LAST_BCK="$(calc_hours_diff "$LAST_ARCHIVE_DATE" "$CURRENT_DATE")"
# in case the date parsing from BORG didn't work (e.g. archive with space in it), datediff will output # in case the date parsing from BORG didn't work (e.g. archive with space in it), datediff will output
# a usage message on stdout and will break prometheus formatting. We need to # a usage message on stdout and will break prometheus formatting. We need to
@@ -182,13 +191,18 @@ function findRepositorysAndGetData() {
} }
function sendDataToGatewayOrNodeExplorer() { function sendDataToGatewayOrNodeExplorer() {
if ! grep -qE '^borg_[a-zA-Z_]+\{[^}]+\} [0-9]' "$TMP_FILE"; then
echo "No valid borg metric data collected; keeping previous metrics output untouched."
return 1
fi
if [ -n "${PUSHGATEWAY_URL}" ]; then if [ -n "${PUSHGATEWAY_URL}" ]; then
#send data via pushgateway #send data via pushgateway
cat $TMP_FILE | curl --data-binary @- ${PUSHGATEWAY_URL}/metrics/job/borg-exporter/host/$HOSTNAME/repository/$REPOSITORY curl --data-binary @"$TMP_FILE" "${PUSHGATEWAY_URL}/metrics/job/borg-exporter/host/$HOSTNAME/repository/${REPOSITORY:-auto}"
else else
#send data via node_exporter #send data via node_exporter
if [ -d "${NODE_EXPORTER_DIR}" ]; then if [ -d "${NODE_EXPORTER_DIR}" ]; then
cp $TMP_FILE ${NODE_EXPORTER_DIR}/borg_exporter.prom mv "$TMP_FILE" "${NODE_EXPORTER_DIR}/borg_exporter.prom"
else else
echo "Please configure either PUSHGATEWAY_URL or NODE_EXPORTER_DIR in /etc/borg_exporter.rc" echo "Please configure either PUSHGATEWAY_URL or NODE_EXPORTER_DIR in /etc/borg_exporter.rc"
fi fi
@@ -196,12 +210,12 @@ function sendDataToGatewayOrNodeExplorer() {
} }
function cleanup() { function cleanup() {
rm -f $TMP_FILE rm -f "$TMP_FILE"
} }
############################################################################################################################## ###################################################################################################
# Main Code # Main Code
############################################################################################################################## ###################################################################################################
writeDefinitionsToMetrics writeDefinitionsToMetrics
if [ -n "${REPOSITORY}" ]; then if [ -n "${REPOSITORY}" ]; then
getBorgDataForRepository "${REPOSITORY}" "${HOSTNAME}" getBorgDataForRepository "${REPOSITORY}" "${HOSTNAME}"
+1
View File
@@ -16,6 +16,7 @@ PubkeyAuthentication yes
AuthenticationMethods publickey AuthenticationMethods publickey
PermitEmptyPasswords no PermitEmptyPasswords no
AuthorizedKeysFile .ssh/authorized_keys AuthorizedKeysFile .ssh/authorized_keys
PermitUserEnvironment yes
StrictModes yes StrictModes yes
AllowUsers borg AllowUsers borg