diff --git a/bin/pdm-build b/bin/pdm-build index 8a0ec65..d9a6539 100755 --- a/bin/pdm-build +++ b/bin/pdm-build @@ -4,19 +4,17 @@ quit() { if [[ $1 == 0 || $FLAGS_debug == $FLAGS_FALSE ]]; then podman rm -i -f tmp-$epoch 2>&1 > /dev/null - podman rmi tmp:$epoch 2>&1 > /dev/null fi exit $1 } -libdir=/tank/local/podman/lib -today=$(date "+%Y-%m-%d-T%H%M") -epoch=$(date "+%s.%3N") +epoch=$(date +%s.%3N) +today=$(date +%Y-%m-%d-T%H%M) # Handle flags -source $libdir/shflags +source shflags DEFINE_boolean 'squash' false 'squash newly built layers into a single new layer' 's' -DEFINE_boolean 'debug' false "Don't delete temporary image/container on build fail" 'd' +DEFINE_boolean 'debug' false "Don't delete temporary container on build fail" 'd' DEFINE_string 'tag' 'latest' 'Tag (other than date) to assign to the image' 't' FLAGS_HELP="Usage: $0 [-s] [-d] [-t tag] [directory] [name] @@ -57,21 +55,21 @@ else name=$(basename $(pwd)) fi +# build options +buildopts="" if [[ $FLAGS_squash == $FLAGS_TRUE ]]; then - buildopts="--squash" -else - buildopts="" + buildopts="$buildopts --squash" fi # Main # build image -echo "Building container ..." -podman build -f Containerfile -t tmp:$epoch $buildopts || quit $? +echo "Building image ..." +podman build -f Containerfile -t tmp $buildopts || quit $? # start container echo "Creating container ..." -podman create --name tmp-$epoch tmp:$epoch || quit $? +podman create --name tmp-$epoch tmp || quit $? podman start tmp-$epoch || quit $? # Systemdfile is for commands that need systemd to execute echo "Running build steps that require systemd ..." diff --git a/bin/pdm-launch b/bin/pdm-launch index 919f468..fad92fd 100755 --- a/bin/pdm-launch +++ b/bin/pdm-launch @@ -1,12 +1,7 @@ #!/bin/bash -# potential flags: deploy config other than default, overwrite - -# Variables -libdir=/tank/local/podman/lib - # Handle flags -source $libdir/shflags +source shflags DEFINE_boolean 'overwrite' false 'Overwrite container if one with same name already exists.' 'o' DEFINE_boolean 'config' false "Automatically configure container with deploy options stored in image metadata." 'c' DEFINE_string 'deployopts' 'deployopts' 'Image metadata label from which to get the deploy options.' 'd' diff --git a/lib/shflags b/bin/shflags similarity index 100% rename from lib/shflags rename to bin/shflags diff --git a/src/debian/Containerfile b/src/debian/Containerfile index 8da200f..777a5fa 100644 --- a/src/debian/Containerfile +++ b/src/debian/Containerfile @@ -2,6 +2,8 @@ FROM debian:stable CMD [ "/sbin/init" ] ENTRYPOINT [ "/sbin/init" ] +WORKDIR /root/ + # We can't use timedatectl because systemd isn't available # during the build process, so we have to set the timezone manually ENV TZ=US/Central @@ -12,7 +14,7 @@ RUN rm /etc/localtime && \ # Install packages RUN apt update -y RUN apt upgrade -y -RUN apt install -y init sudo wget nano less man-db +RUN apt install -y init sudo wget nano less man-db unzip RUN apt autoremove -y --purge RUN apt clean -y diff --git a/src/gitea/Containerfile b/src/gitea/Containerfile new file mode 100644 index 0000000..9eed7e4 --- /dev/null +++ b/src/gitea/Containerfile @@ -0,0 +1,94 @@ +### +### Build Variables +### +FROM localhost/debian:latest + +# deploy options +# -p (port) and -v (volume) both go host:container +LABEL deployopts="\ +-p 9081:80 \ +-p 9022:22 \ +-v /tank/files/git:/vol/git \ +-v /tank/files/db/gitea:/vol/db" +# make sure mount directories exist +RUN mkdir -p /vol/git /vol/db + +# version of postgres +ARG psqlv=11 +# uid that the files owner user should have +ARG FILESUID=5000 + +# Container Variables +# database name and user +ENV DBUSER=gtadmin +ENV DBNAME=gitea +# put environment variables in /etc/environment so we can access them from cron scripts +RUN echo "DBUSER=$DBUSER" >> /etc/environment && \ + echo "DBNAME=$DBNAME" >> /etc/environment + +### +### General Setup +### + +# install packages we want +RUN apt update -y && apt install -y postgresql postgresql-doc git + +# create gitea user with file owner UID +RUN addgroup --gid $FILESUID gitea && \ + adduser gitea --ingroup gitea --uid $FILESUID --disabled-password --gecos "Gitea Server" --shell /usr/sbin/nologin + +# copy our custom scripts +COPY resources/bin/ /usr/local/bin/ + +### +### PostgreSQL ### +### + +# configure PostgreSQL access +COPY --chown=postgres:postgres resources/pg_hba.conf /etc/postgresql/${psqlv}/main/pg_hba.conf + +### +### Gitea +### + +# dowload gitea +RUN wget https://dl.gitea.io/gitea/master/gitea-master-linux-amd64 && \ + mv gitea-master-linux-amd64 /usr/local/bin/gitea && \ + chmod +x /usr/local/bin/gitea + +# make directories gitea needs +RUN mkdir -p /var/lib/gitea/ && \ + cd /var/lib/gitea/ && \ + mkdir custom data log && \ + chown -R gitea:gitea /var/lib/gitea/ && \ + chmod -R 750 /var/lib/gitea/ + +# copy gitea config template +COPY resources/app.ini.esh /etc/gitea/ +# template config file +RUN cd /etc/gitea/ && \ + esh app.ini.esh > app.ini && \ + rm app.ini.esh && \ + chmod -R +r /etc/gitea/ + +COPY resources/gitea.service /etc/systemd/system/ + +### +### Crontab +### +COPY resources/crontab /root/ +RUN crontab -u gitea /root/crontab + +### +### Systemdfile +### +COPY Systemdfile /root/ +RUN chmod +x /root/Systemdfile + +### +### Bugfix +### + +# execute command to workaround bug in cron +COPY bugfix/cronfix /root/ +RUN chmod +x /root/cronfix && /root/cronfix diff --git a/src/gitea/Systemdfile b/src/gitea/Systemdfile new file mode 100644 index 0000000..469fa94 --- /dev/null +++ b/src/gitea/Systemdfile @@ -0,0 +1,14 @@ +#!/bin/bash + +# fail if any command returns error +set -e +set -x +# wait 5 seconds to make sure all services have finished starting up +sleep 5 + +# make database for gitea +db-make + +# enable and start gitea +systemctl enable gitea +systemctl start gitea diff --git a/src/gitea/bugfix/cronfix b/src/gitea/bugfix/cronfix new file mode 100644 index 0000000..483c9dc --- /dev/null +++ b/src/gitea/bugfix/cronfix @@ -0,0 +1,2 @@ +#!/bin/sh +sed -i '/session required pam_loginuid.so/c\#session required pam_loginuid.so' /etc/pam.d/cron diff --git a/src/gitea/resources/app.ini.esh b/src/gitea/resources/app.ini.esh new file mode 100644 index 0000000..2fca524 --- /dev/null +++ b/src/gitea/resources/app.ini.esh @@ -0,0 +1,69 @@ +APP_NAME = Gitea: Git with a cup of tea +RUN_USER = gitea +RUN_MODE = prod + +[oauth2] +JWT_SECRET = <%= $(gitea generate secret JWT_SECRET) %> + +[security] +INTERNAL_TOKEN = <%= $(gitea generate secret INTERNAL_TOKEN) %> +INSTALL_LOCK = true +SECRET_KEY = <%= $(gitea generate secret SECRET_KEY) %> +; disable password complexity checks +PASSWORD_COMPLEXITY = off + +[database] +DB_TYPE = postgres +HOST = /var/run/postgresql +NAME = gitea +USER = gtadmin +PASSWD = +SSL_MODE = disable +CHARSET = utf8 +PATH = /var/lib/gitea/data/gitea.db + +[repository] +ROOT = /vol/git/repos + +[server] +DOMAIN = medusa.alemor.org +ROOT_URL = http://medusa.casa.alemor.org/git/ +HTTP_PORT = 80 +START_SSH_SERVER = true +SSH_PORT = 9022 +SSH_LISTEN_PORT = 22 +LFS_START_SERVER = trxue +LFS_CONTENT_PATH = /vol/git/lfs +LFS_JWT_SECRET = <%= $(gitea generate secret JWT_SECRET) %> +OFFLINE_MODE = true + +[mailer] +ENABLED = false + +[service] +REGISTER_EMAIL_CONFIRM = false +ENABLE_NOTIFY_MAIL = false +DISABLE_REGISTRATION = true +ALLOW_ONLY_EXTERNAL_REGISTRATION = false +ENABLE_CAPTCHA = false +REQUIRE_SIGNIN_VIEW = false +DEFAULT_KEEP_EMAIL_PRIVATE = false +DEFAULT_ALLOW_CREATE_ORGANIZATION = false +DEFAULT_ENABLE_TIMETRACKING = true +NO_REPLY_ADDRESS = noreply.localhost + +[picture] +DISABLE_GRAVATAR = true +ENABLE_FEDERATED_AVATAR = false + +[openid] +ENABLE_OPENID_SIGNIN = true +ENABLE_OPENID_SIGNUP = false + +[session] +PROVIDER = file + +[log] +MODE = file +LEVEL = info +ROOT_PATH = /var/lib/gitea/log diff --git a/src/gitea/resources/bin/db-dump b/src/gitea/resources/bin/db-dump new file mode 100755 index 0000000..411a6a8 --- /dev/null +++ b/src/gitea/resources/bin/db-dump @@ -0,0 +1,2 @@ +#!/bin/bash +pg_dump -O -U $DBUSER -d $DBNAME -f $1 diff --git a/src/gitea/resources/bin/db-load b/src/gitea/resources/bin/db-load new file mode 100755 index 0000000..a070565 --- /dev/null +++ b/src/gitea/resources/bin/db-load @@ -0,0 +1,3 @@ +#!/bin/bash +db-make +psql -U $DBUSER -d $DBNAME -f $1 diff --git a/src/gitea/resources/bin/db-make b/src/gitea/resources/bin/db-make new file mode 100755 index 0000000..c34ee09 --- /dev/null +++ b/src/gitea/resources/bin/db-make @@ -0,0 +1,12 @@ +#!/bin/bash + +cmd() { + sudo -u postgres psql -c "$1" +} + +cd /var/lib/postgresql +cmd "DROP DATABASE IF EXISTS $DBNAME;" +cmd "DROP USER IF EXISTS $DBUSER;" +cmd "CREATE USER $DBUSER;" +cmd "CREATE DATABASE $DBNAME WITH TEMPLATE template0 ENCODING UTF8 LC_COLLATE 'C.UTF-8' LC_CTYPE 'C.UTF-8';" +cmd "GRANT ALL PRIVILEGES ON DATABASE $DBNAME TO $DBUSER;" diff --git a/src/gitea/resources/bin/esh b/src/gitea/resources/bin/esh new file mode 100755 index 0000000..71698a3 --- /dev/null +++ b/src/gitea/resources/bin/esh @@ -0,0 +1,366 @@ +#!/bin/sh +# vim: set ts=4: +#---help--- +# USAGE: +# esh [options] [--] [...] +# esh <-h | -V> +# +# Process and evaluate an ESH template. +# +# ARGUMENTS: +# Path of the template file or "-" to read from STDIN. +# Variable(s) specified as = to pass into the +# template (the have higher priority than environment +# variables). +# +# OPTIONS: +# -d Don't evaluate template, just dump a shell script. +# -o Output file or "-" for STDOUT. Defaults to "-". +# -s Command name or path of the shell to use for template +# evaluation. It must not contain spaces. +# Defaults to "/bin/sh". +# -h Show this help message and exit. +# -V Print version and exit. +# +# ENVIRONMENT: +# ESH_AWK Command name of path of the awk program to use. +# It must not contain spaces. Defaults to "awk". +# ESH_MAX_DEPTH Maximum include depth. Defaults to 3. +# ESH_SHELL Same as -s. +# +# EXIT STATUS: +# 0 Clean exit, no error has encountered. +# 1 Generic error. +# 10 Invalid usage. +# 11 ESH syntax error. +# 12 Include error: file not found. +# 13 Include error: exceeded max include depth (ESH_MAX_DEPTH). +# +# Please report bugs at . +#---help--- +set -eu + +readonly PROGNAME='esh' +readonly VERSION='0.3.0' +readonly SCRIPTPATH="$0" + +AWK_CONVERTER=$(cat <<'AWK' +function fail(code, msg) { + state = "ERROR" + # FIXME: /dev/stderr is not portable + printf("%s: %s\n", line_info(), msg) > "/dev/stderr" + exit code +} +function line_info() { + return FILENAME ? (filenames[depth] ":" linenos[depth]) : "(init)" # (init) if inside BEGIN +} +# IMPORTANT: This is the only function that should print a newline. +function puts(str) { + print(line_info()) > MAP_FILE + print(str) +} +function fputs(str) { + printf("%s", str) +} +function trim(str) { + gsub(/^[ \t\r\n]+|[ \t\r\n]+$/, "", str) + return str +} +function read(len, _str) { + if (len == "") { + _str = buff + buff = "" + } else if (len > 0) { + _str = substr(buff, 1, len) + buff = substr(buff, len + 1, length(buff)) + } + return _str +} +function skip(len) { + buff = substr(buff, len + 1, length(buff)) +} +function flush(len, _str) { + _str = read(len) + + if (state == "TEXT") { + gsub("'", "'\\''", _str) + } + if (state != "COMMENT") { + fputs(_str) + } +} +function file_exists(filename, _junk) { + if ((getline _junk < filename) >= 0) { + close(filename) + return 1 + } + return 0 +} +function dirname(path) { + return sub(/\/[^\/]+\/*$/, "/", path) ? path : "" +} +function include(filename) { + if (index(filename, "/") != 1) { # if does not start with "/" + filename = dirname(filenames[depth]) filename + } + if (!file_exists(filename)) { + fail(12, "cannot include " filename ": not a file or not readable") + } + if (depth > MAX_DEPTH) { + fail(13, "cannot include " filename ": exceeded maximum depth of " MAX_DEPTH) + } + buffs[depth] = buff + states[depth] = state + filenames[depth + 1] = filename + depth++ + + init() + while ((getline buff < filename) > 0) { + if (print_nl && state != "COMMENT") { + puts("") + } + process_line() + } + end_text() + close(filename) + + depth-- + buff = buffs[depth] + state = states[depth] +} +function init() { + buff = "" + linenos[depth] = 0 + print_nl = 0 + start_text() +} +function start_text() { + puts("") + fputs("printf '%s' '") + state = "TEXT" +} +function end_text() { + if (state != "TEXT") { return } + puts("' #< " line_info()) + state = "UNDEF" +} +function process_line() { + linenos[depth]++ + + while (buff != "") { + print_nl = 1 + + if (state == "TEXT" && match(buff, /<%/)) { + flush(RSTART - 1) # print buff before "<%" + skip(2) # skip "<%" + + flag = substr(buff, 1, 1) + if (flag != "%") { + end_text() + } + if (flag == "%") { # <%% + skip(1) + fputs("<%") + } else if (flag == "=") { # <%= + skip(1) + fputs("__print ") + state = "TAG" + } else if (flag == "+") { # <%+ + if (!match(buff, /[^%]%>/)) { + fail(11, "syntax error: <%+ must be closed on the same line") + } + filename = trim(substr(buff, 2, match(buff, /.-?%>/) - 1)) + skip(RSTART) + include(filename) + state = "TAG" + } else if (flag == "#") { # <%# + state = "COMMENT" + } else { + state = "TAG" + } + } else if (state != "TEXT" && match(buff, /%>/)) { + flag = RSTART > 1 ? substr(buff, RSTART - 1, 1) : "" + + if (flag == "%") { # %%> + flush(RSTART - 2) + skip(1) + flush(2) + } else if (flag == "-") { # -%> + flush(RSTART - 2) + skip(3) + print_nl = 0 + } else { # %> + flush(RSTART - 1) + skip(2) + } + if (flag != "%") { + start_text() + } + } else { + flush() + } + } +} +BEGIN { + FS = "" + depth = 0 + + puts("#!" (SHELL ~ /\// ? SHELL : "/usr/bin/env " SHELL)) + puts("set -eu") + puts("if ( set -o pipefail 2>/dev/null ); then set -o pipefail; fi") + puts("__print() { printf '%s' \"$*\"; }") + + split(VARS, _lines, /\n/) + for (_i in _lines) { + puts(_lines[_i]) + } + init() +} +{ + if (NR == 1) { + filenames[0] = FILENAME # this var is not defined in BEGIN so we must do it here + } + buff = $0 + process_line() + + if (print_nl && state != "COMMENT") { + puts("") + } +} +END { + end_text() +} +AWK +) +AWK_ERR_FILTER=$(cat <<'AWK' +function line_info(lno, _line, _i) { + while ((getline _line < MAPFILE) > 0 && _i++ < lno) { } + close(MAPFILE) + return _line +} +{ + if (match($0, "^" SRCFILE ":( line)? ?[0-9]+:") && match(substr($0, 1, RLENGTH), /[0-9]+:$/)) { + lno = substr($0, RSTART, RLENGTH - 1) + 0 + msg = substr($0, RSTART + RLENGTH + 1) # v-- some shells duplicate filename + msg = index(msg, SRCFILE ":") == 1 ? substr(msg, length(SRCFILE) + 3) : msg + print(line_info(lno) ": " msg) + } else if ($0 != "") { + print($0) + } +} +AWK +) +readonly AWK_CONVERTER AWK_ERR_FILTER + +print_help() { + sed -En '/^#---help---/,/^#---help---/p' "$SCRIPTPATH" | sed -E 's/^# ?//; 1d;$d;' +} + +filter_shell_stderr() { + $ESH_AWK \ + -v SRCFILE="$1" \ + -v MAPFILE="$2" \ + -- "$AWK_ERR_FILTER" +} + +evaluate() { + local srcfile="$1" + local mapfile="$2" + + # This FD redirection magic is for swapping stdout/stderr back and forth. + exec 3>&1 + { set +e; $ESH_SHELL "$srcfile" 2>&1 1>&3; echo $? >>"$mapfile"; } \ + | filter_shell_stderr "$srcfile" "$mapfile" >&2 + exec 3>&- + + return $(tail -n 1 "$mapfile") +} + +convert() { + local input="$1" + local vars="$2" + local map_file="${3:-"/dev/null"}" + + $ESH_AWK \ + -v MAX_DEPTH="$ESH_MAX_DEPTH" \ + -v SHELL="$ESH_SHELL" \ + -v MAP_FILE="$map_file" \ + -v VARS="$vars" \ + -- "$AWK_CONVERTER" "$input" +} + +process() { + local input="$1" + local vars="$2" + local evaluate="${3:-yes}" + local ret=0 tmpfile mapfile + + if [ "$evaluate" = yes ]; then + tmpfile=$(mktemp) + mapfile=$(mktemp) + + convert "$input" "$vars" "$mapfile" > "$tmpfile" || ret=$? + test $ret -ne 0 || evaluate "$tmpfile" "$mapfile" || ret=$? + + rm -f "$tmpfile" "$mapfile" + else + convert "$input" "$vars" || ret=$? + fi + return $ret +} + +: ${ESH_AWK:="awk"} +: ${ESH_MAX_DEPTH:=3} +: ${ESH_SHELL:="/bin/sh"} +EVALUATE='yes' +OUTPUT='' + +while getopts ':dho:s:V' OPT; do + case "$OPT" in + d) EVALUATE=no;; + h) print_help; exit 0;; + o) OUTPUT="$OPTARG";; + s) ESH_SHELL="$OPTARG";; + V) echo "$PROGNAME $VERSION"; exit 0;; + '?') echo "$PROGNAME: unknown option: -$OPTARG" >&2; exit 10;; + esac +done +shift $(( OPTIND - 1 )) + +if [ $# -eq 0 ]; then + printf "$PROGNAME: %s\n\n" 'missing argument ' >&2 + print_help >&2 + exit 10 +fi + +INPUT="$1"; shift +[ "$INPUT" != '-' ] || INPUT='' +if [ "$INPUT" ] && ! [ -f "$INPUT" -a -r "$INPUT" ]; then + echo "$PROGNAME: can't read $INPUT: not a file or not readable" >&2; exit 10 +fi + +# Validate arguments. +for arg in "$@"; do + case "$arg" in + *=*) ;; + *) echo "$PROGNAME: illegal argument: $arg" >&2; exit 10;; + esac +done + +# Format variables into shell variable assignments. +vars=''; for item in "$@"; do + vars="$vars\n${item%%=*}='$( + printf %s "${item#*=}" | $ESH_AWK "{ gsub(/'/, \"'\\\\\\\''\"); print }" + )'" +done + +export ESH="$0" + +if [ "${OUTPUT#-}" ]; then + tmpfile="$(mktemp)" + trap "rm -f '$tmpfile'" EXIT HUP INT TERM + process "$INPUT" "$vars" "$EVALUATE" > "$tmpfile" + mv "$tmpfile" "$OUTPUT" +else + process "$INPUT" "$vars" "$EVALUATE" +fi diff --git a/src/gitea/resources/bin/maint b/src/gitea/resources/bin/maint new file mode 100755 index 0000000..85f6f89 --- /dev/null +++ b/src/gitea/resources/bin/maint @@ -0,0 +1,41 @@ +#!/bin/bash + +# load environment variables +source /etc/environment + +hour=$(date +%H) +day=$(date +%d) +month=$(date +%m) +year=$(date +%Y) + +dumpdir=/vol/db +errlog=error/$year-$month-$day-T$hour.log + +mkdir -p $dumpdir/error +cd $dumpdir + +if [[ $# -lt 2 ]]; then + echo "Error: called with missing hour and/or day parameter. Script exited without running." | tee $errlog + exit 1 +fi + +if [[ $hour == $1 ]]; then + nc-occ maintenance:mode --on +fi + +db-dump $DBNAME-hourly-$hour.sql 2>> $errlog + +if [[ $hour == $1 ]]; then + nc-occ maintenance:mode --off + mv $DBNAME-hourly-$hour.sql $DBNAME-daily-$day.sql 2>> $errlog + + if [[ $day == $2 ]]; then + mv $DBNAME-daily-$day.sql $DBNAME-$year-$month-$day.sql 2>> $errlog + fi +fi + +# If error log is size 0, erase it because I don't like seeing it +if [[ ! -s $errlog ]]; then + rm $errlog + rmdir --ignore-fail-on-non-empty error +fi diff --git a/src/gitea/resources/crontab b/src/gitea/resources/crontab new file mode 100644 index 0000000..38142c9 --- /dev/null +++ b/src/gitea/resources/crontab @@ -0,0 +1,5 @@ +PATH=/usr/local/bin:/bin:/usr/bin +# m h dom mon dow command + +# Dump database every hour +23 * * * * maint 01 01 diff --git a/src/gitea/resources/gitea.service b/src/gitea/resources/gitea.service new file mode 100644 index 0000000..57f11d0 --- /dev/null +++ b/src/gitea/resources/gitea.service @@ -0,0 +1,33 @@ +[Unit] +Description=Gitea (Git with a cup of tea) +After=syslog.target +After=network.target +Requires=postgresql.service + +[Service] +# Modify these two values and uncomment them if you have +# repos with lots of files and get an HTTP error 500 because +# of that +### +#LimitMEMLOCK=infinity +#LimitNOFILE=65535 +RestartSec=2s +Type=simple +User=gitea +Group=gitea +WorkingDirectory=/var/lib/gitea/ +# If using Unix socket: tells systemd to create the /run/gitea folder, which will contain the gitea.sock file +# (manually creating /run/gitea doesn't work, because it would not persist across reboots) +#RuntimeDirectory=gitea +ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini +Restart=always +Environment=USER=gitea HOME=/home/gitea GITEA_WORK_DIR=/var/lib/gitea +# If you want to bind Gitea to a port below 1024, uncomment +# the two values below, or use socket activation to pass Gitea its ports as above +### +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +AmbientCapabilities=CAP_NET_BIND_SERVICE +### + +[Install] +WantedBy=multi-user.target diff --git a/src/gitea/resources/pg_hba.conf b/src/gitea/resources/pg_hba.conf new file mode 100644 index 0000000..bf55f34 --- /dev/null +++ b/src/gitea/resources/pg_hba.conf @@ -0,0 +1 @@ +local all all trust diff --git a/src/nextcloud/Containerfile b/src/nextcloud/Containerfile index 8c8e2f4..4085abd 100644 --- a/src/nextcloud/Containerfile +++ b/src/nextcloud/Containerfile @@ -5,36 +5,40 @@ FROM localhost/debian # deploy options # -p (port) and -v (volume) both go host:container -LABEL deployopts="-p 4380:80 \ +LABEL deployopts="\ +-p 9080:80 \ -v /tank/files/user/mar:/vol/files/mar/files \ -v /tank/files/db/nextcloud:/vol/db" -# make directories that we will be mounting into +# make sure mount directories exist RUN mkdir -p /vol/files/mar/files /vol/db -# php and postgres versions. will depend on version of debian we are running +# Build Variables +# versions of php and postgres ARG phpv=7.3 ARG psqlv=11 +# uid that the files owner user should have +ARG FILESUID=5000 -# database variables +# Environment Variables +# database name and user ENV DBUSER=ncadmin ENV DBNAME=nextcloud +# put environment variables in /etc/environment so we can access them from cron scripts +RUN echo "DBUSER=$DBUSER" >> /etc/environment && \ + echo "DBNAME=$DBNAME" >> /etc/environment ### ### General Setup ### # install packages we want -RUN apt update -y && apt install -y systemd sudo wget apache2 php-fpm \ - php-gd php-zip php-pgsql php-curl php-mbstring php-intl php-imagick \ - php-xml php-json redis php-redis postgresql postgresql-doc \ - unzip php-ldap - -# this is a bug workaround b/c testing is currently between versions of php. should be removed ideally -RUN update-alternatives --set php /usr/bin/php7.3 +RUN apt update -y && apt install -y apache2 php-fpm php-gd php-zip \ + php-pgsql php-curl php-mbstring php-intl php-imagick php-xml \ + php-json redis php-redis postgresql postgresql-doc php-ldap # change www-data's UID to the file owner UID -RUN usermod --uid 5000 www-data && \ - groupmod --gid 5000 www-data && \ +RUN usermod --uid $FILESUID www-data && \ + groupmod --gid $FILESUID www-data && \ chown -R www-data:www-data /var/www /vol # copy our custom scripts @@ -99,9 +103,8 @@ COPY --chown=www-data:www-data resources/my.config.php nextcloud/config/ ### Crontab ### COPY resources/crontab /root/ -# the sed command is needed to workaround a bug in cron -RUN sed -i '/session required pam_loginuid.so/c\#session required pam_loginuid.so' /etc/pam.d/cron && \ - crontab -u www-data /root/crontab +# crontab for www-data +RUN crontab -u www-data /root/crontab ### ### Systemdfile @@ -115,3 +118,7 @@ RUN chmod +x /root/Systemdfile # push the fixed systemd file for redis COPY bugfix/redis.service /etc/systemd/system/redis.service + +# execute command to workaround bug in cron +COPY bugfix/cronfix /root/ +RUN chmod +x /root/cronfix && /root/cronfix diff --git a/src/nextcloud/bugfix/cronfix b/src/nextcloud/bugfix/cronfix new file mode 100644 index 0000000..483c9dc --- /dev/null +++ b/src/nextcloud/bugfix/cronfix @@ -0,0 +1,2 @@ +#!/bin/sh +sed -i '/session required pam_loginuid.so/c\#session required pam_loginuid.so' /etc/pam.d/cron diff --git a/src/nextcloud/resources/bin/maint b/src/nextcloud/resources/bin/maint index 031582d..85f6f89 100755 --- a/src/nextcloud/resources/bin/maint +++ b/src/nextcloud/resources/bin/maint @@ -1,17 +1,21 @@ #!/bin/bash +# load environment variables +source /etc/environment + hour=$(date +%H) day=$(date +%d) month=$(date +%m) year=$(date +%Y) dumpdir=/vol/db +errlog=error/$year-$month-$day-T$hour.log -mkdir -p $dumpdir +mkdir -p $dumpdir/error cd $dumpdir if [[ $# -lt 2 ]]; then - echo "[$year-$month-$day] Error: called with missing hour and/or day parameter. Script exited without running." | tee error.log + echo "Error: called with missing hour and/or day parameter. Script exited without running." | tee $errlog exit 1 fi @@ -19,18 +23,19 @@ if [[ $hour == $1 ]]; then nc-occ maintenance:mode --on fi -db-dump $DBNAME-hourly-$hour.sql 2>> error.log +db-dump $DBNAME-hourly-$hour.sql 2>> $errlog if [[ $hour == $1 ]]; then nc-occ maintenance:mode --off - mv $DBNAME-hourly-$hour.sql $DBNAME-daily-$day.sql 2>> error.log + mv $DBNAME-hourly-$hour.sql $DBNAME-daily-$day.sql 2>> $errlog if [[ $day == $2 ]]; then - mv $DBNAME-daily-$day.sql $DBNAME-$year-$month-$day.sql 2>> error.log + mv $DBNAME-daily-$day.sql $DBNAME-$year-$month-$day.sql 2>> $errlog fi fi -# If error.log is size 0, erase it because I don't like seeing it -if [[ ! -s ./error.log ]]; then - rm error.log +# If error log is size 0, erase it because I don't like seeing it +if [[ ! -s $errlog ]]; then + rm $errlog + rmdir --ignore-fail-on-non-empty error fi diff --git a/src/nextcloud/resources/crontab b/src/nextcloud/resources/crontab index 37704db..7c3641a 100644 --- a/src/nextcloud/resources/crontab +++ b/src/nextcloud/resources/crontab @@ -1,8 +1,11 @@ PATH=/usr/local/bin:/bin:/usr/bin # m h dom mon dow command + # Run Nextcloud cron tasks every 5 minutes */5 * * * * php -f /var/www/html/nextcloud/cron.php -# Dump database every hour -10 * * * * maint 01 01 + # Scan for new files every 15 minutes */15 * * * * nc-occ files:scan --all + +# Dump database every hour +23 * * * * maint 01 01