6 Commits

Author SHA1 Message Date
Nick Stokoe
4fddb06060 templates/docker-compose/upmpdcli/ - bump alpine to 3.21 2025-05-28 12:22:32 +01:00
Nick Stokoe
c0b289d2bc templates/docker-compose/proxy/Dockerfile - bump to alpine-0.7 2025-05-28 12:22:32 +01:00
Nick Stokoe
ce18785ccb templates/docker-compose/navidrome/Dockerfile - bump to 55.2 2025-05-28 12:22:32 +01:00
Nick Stokoe
ca24f7dae7 templates/docker-compose/ - update Borgmatics image
It's necessary to update to the `latest` image because the
`latest-msmtp` image is now unmaintained and doesn't support postgres
17.

However, this means we need to adjust things (the backup script and
the environment variable config) because we need to use the latest
notification mechanism, `apprise` instead of msmtp.

Tested, seems to be working.
2025-05-28 12:22:32 +01:00
Nick Stokoe
5ca9ecfe2a templates/docker-compose/borgmatic/ - avoid losing STDERR lines
use stdbuf to change the buffereing mode to be linewise
2025-05-28 12:22:32 +01:00
Nick Stokoe
4fecd838ae templates/docker-compose/web/ - fix nginx.conf for latest NC 2025-05-28 12:18:33 +01:00
9 changed files with 272 additions and 172 deletions

View File

@@ -1,2 +1,3 @@
POSTGRES_PASSWORD={{ nextcloud_db_password }} POSTGRES_PASSWORD={{ nextcloud_db_password }}
BORG_PASSPHRASE={{ borg_passphrase }} BORG_PASSPHRASE={{ borg_passphrase }}
SMTP_PASSWORD={{ smtp_password }}

View File

@@ -1,4 +1,11 @@
FROM b3vis/borgmatic:latest-msmtp FROM b3vis/borgmatic:latest
# Install stdbuf, used by backup.sh
RUN \
echo "* Installing Runtime Packages" \
&& apk upgrade --no-cache \
&& echo "* Installing Runtime Packages" \
&& apk add -U --no-cache \
coreutils
COPY --chmod=755 backup.sh /backup.sh COPY --chmod=755 backup.sh /backup.sh

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# Run the backup and mail the logs: # Run the backup and mail the logs:
# Depending on parameter 1: # Depending on parameter 1:
# - test-smtp: just send a test email to $MAIL_TO # - test-smtp: just send a test email using $APPRISE_URI
# - run: create the backup, no checks # - run: create the backup, no checks
# - check: prune, compact and check the backup # - check: prune, compact and check the backup
# Anything else is an error. # Anything else is an error.
@@ -9,8 +9,6 @@
set -o pipefail set -o pipefail
# Set up environment # Set up environment
/bin/sh /scripts/msmtprc.sh
/bin/sh /scripts/env.sh
RUN_COMMAND="borgmatic --stats -v 2 create" RUN_COMMAND="borgmatic --stats -v 2 create"
CHECK_COMMAND="borgmatic --stats -v 1 prune compact check" CHECK_COMMAND="borgmatic --stats -v 1 prune compact check"
LOGFILE="/tmp/backup_run_$(date +%s).log" LOGFILE="/tmp/backup_run_$(date +%s).log"
@@ -31,7 +29,7 @@ indent() {
log() { log() {
# Adapted from https://stackoverflow.com/a/31151808 # Adapted from https://stackoverflow.com/a/31151808
{ {
"$@" 2>&1 1>&3 3>&- | indent " ! " stdbuf -oL -eL "$@" 2>&1 1>&3 3>&- | indent " ! "
} 3>&1 1>&2 | indent " | " | tee -a "$LOGFILE" } 3>&1 1>&2 | indent " | " | tee -a "$LOGFILE"
} }
@@ -43,14 +41,12 @@ report() {
log echo "FAILED: $RESULT" log echo "FAILED: $RESULT"
PREFIX="$FAILED_PREFIX" PREFIX="$FAILED_PREFIX"
fi fi
printf "Subject: %s: '%s'\n\n%s\n" "$PREFIX" "$PARAM" "$(cat $LOGFILE)" | apprise -vv -t "$PREFIX: '$PARAM'" -b "$(cat $LOGFILE)" "$APPRISE_URI&pass=$SMTP_PASSWORD"
sendmail -t "$MAIL_TO"
log echo "Report sent." log echo "Report sent."
} }
testmail() { testmail() {
echo -e "Subject: TESTING!\n\ntest mail, please ignore\n" | apprise -vv -t "TESTING!" -b "test mail, please ignore." "$APPRISE_URI&pass=$SMTP_PASSWORD"
sendmail -t "$MAIL_TO"
} }
failed() { failed() {
@@ -72,7 +68,7 @@ trap cleanup EXIT
case "$PARAM" in case "$PARAM" in
test-smtp) test-smtp)
echo "Testing mail to $MAIL_TO" echo "Testing mail to via Apprise ($APPRISE_URI)"
testmail testmail
echo "Done." echo "Done."
;; ;;

View File

@@ -260,20 +260,18 @@ services:
- ./volumes/borg-ssh-config:/root/.ssh/ # ssh keys; sshd writes knownhosts etc here - ./volumes/borg-ssh-config:/root/.ssh/ # ssh keys; sshd writes knownhosts etc here
environment: environment:
# Work around the use of a fancy init system s6:
# https://github.com/borgmatic-collective/docker-borgmatic/issues/320#issuecomment-2089003361
S6_KEEP_ENV: 1
POSTGRES_USER: nextcloud POSTGRES_USER: nextcloud
POSTGRES_DB: nextcloud POSTGRES_DB: nextcloud
POSTGRES_HOST: postgres POSTGRES_HOST: postgres
BORG_ARCHIVE: nick BORG_ARCHIVE: nick
BORG_ARCHIVE_LABEL: snackpot BORG_ARCHIVE_LABEL: snackpot
MAIL_RELAY_HOST: mail.noodlefactory.co.uk APPRISE_URI: "mailtos://mail.noodlefactory.co.uk:25?user=nc.noodlefactory.co.uk&from=borgmatic@snackpot.noodlefactory.co.uk&to=nick@noodlefactory.co.uk"
MAIL_PORT: 25 # SMTP_PASSWORD is set via borgmatic.env, created via ansible,
MAIL_AUTH_METHOD: login # and appended to APPRISE_URL by borgmatic/backup.sh script
MAIL_STARTTLS: 'on'
MAIL_USER: nc.noodlefactory.co.uk
MAIL_FROM: borgmatic@snackpot.noodlefactory.co.uk
MAIL_TO: nick@noodlefactory.co.uk
MAIL_SUBJECT: Borgmatic Backup
# MAIL_PASSWORD is set via volumes/borgmatic-config/msmtp.env, created via ansible
# Test SMTP auth on the server https://doc.dovecot.org/admin_manual/debugging/debugging_authentication/ # Test SMTP auth on the server https://doc.dovecot.org/admin_manual/debugging/debugging_authentication/
env_file: env_file:
- ./borgmatic.env - ./borgmatic.env

View File

@@ -1,4 +1,4 @@
FROM deluan/navidrome:0.54.4 FROM deluan/navidrome:0.55.2
RUN apk add --no-cache mpv RUN apk add --no-cache mpv
# Ensure that navidrome has access to these directories # Ensure that navidrome has access to these directories

View File

@@ -1,3 +1,3 @@
FROM jwilder/nginx-proxy:alpine-0.7.0 FROM jwilder/nginx-proxy:1.7-alpine
COPY uploadsize.conf /etc/nginx/conf.d/uploadsize.conf COPY uploadsize.conf /etc/nginx/conf.d/uploadsize.conf

View File

@@ -1,4 +1,4 @@
FROM alpine:3.19 FROM alpine:3.21
RUN apk update \ RUN apk update \
&& apk upgrade \ && apk upgrade \

View File

@@ -1,3 +1,3 @@
FROM nginx:1.19.6-alpine FROM nginx:1.28-alpine
COPY nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/conf.d/default.conf

View File

@@ -1,42 +1,40 @@
worker_processes auto; # Adapted from https://docs.nextcloud.com/server/31/admin_manual/installation/nginx.html
# Insert as /etc/nginx/conf.d/default.conf
error_log /var/log/nginx/error.log warn; # Set .mjs and .wasm MIME types
pid /var/run/nginx.pid; # Either include it in the default mime.types list
# and include that list explicitly or add the file extension
# only for Nextcloud like below:
types {
text/javascript mjs;
application/wasm wasm;
}
upstream php-handler {
server nextcloud:9000;
}
events { # Set the `immutable` cache control options only for assets with a cache busting `v` argument
worker_connections 1024; map $arg_v $asset_immutable {
"" "";
default ", immutable";
} }
http { server {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Real-IP;
#gzip on;
upstream php-handler {
server nextcloud:9000;
}
server {
listen 80; listen 80;
server_name nc.noodlefactory.co.uk;
# Prevent nginx HTTP Server Detection
server_tokens off;
# HSTS settings
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
# Add headers to serve security related headers # Add headers to serve security related headers
# Before enabling Strict-Transport-Security headers please read into this # Before enabling Strict-Transport-Security headers please read into this
@@ -53,12 +51,13 @@ http {
add_header X-Download-Options "noopen" always; add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always; add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always; add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak # Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By; fastcgi_hide_header X-Powered-By;
# Path to the root of your installation # Path to the root of your installation
root /var/www/html; root /var/www/html;
@@ -77,97 +76,196 @@ http {
# Uncomment it if you're planning to use this app. # Uncomment it if you're planning to use this app.
#rewrite ^/.well-known/webfinger /public.php?service=webfinger last; #rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
location = /.well-known/carddav { # set max upload size and increase upload timeout
return 301 $scheme://$host:$server_port/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host:$server_port/remote.php/dav;
}
# set max upload size
client_max_body_size 10G; client_max_body_size 10G;
client_body_timeout 300s;
fastcgi_buffers 64 4K; fastcgi_buffers 64 4K;
# The settings allows you to optimize the HTTP2 bandwidth.
# See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
# for tuning hints
client_body_buffer_size 512k;
# Enable gzip but do not remove ETag headers # Enable gzip but do not remove ETag headers
gzip on; gzip on;
gzip_vary on; gzip_vary on;
gzip_comp_level 4; gzip_comp_level 4;
gzip_min_length 256; gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Uncomment if your server is build with the ngx_pagespeed module # Pagespeed is not supported by Nextcloud, so if your server is built
# This module is currently not supported. # with the `ngx_pagespeed` module, uncomment this line to disable it.
#pagespeed off; #pagespeed off;
location / {
rewrite ^ /index.php; # Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 /remote.php/webdav/$is_args$args;
}
} }
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ { # Make a regex exception for `/.well-known` so that clients can still
deny all; # access it despite the existence of the regex rule
} # `location ~ /(\.|autotest|...)` which would otherwise handle requests
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) { # for `/.well-known`.
deny all; location ^~ /.well-known {
# The rules in this block are an adaptation of the rules
# in `.htaccess` that concern `/.well-known`.
location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }
location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
location /.well-known/pki-validation { try_files $uri $uri/ =404; }
# Let Nextcloud's API for `/.well-known` URIs handle all other
# requests by passing them to the front-end controller.
return 301 /index.php$request_uri;
} }
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) { # Rules borrowed from `.htaccess` to hide certain paths from clients
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$; location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
# Ensure this block, which passes PHP files to the PHP process, is above the blocks
# which handle static assets (as seen below). If this block is not declared first,
# then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
# to the URI, resulting in a HTTP 500 error response.
location ~ \.php(?:$|/) {
# Required for legacy support
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info; set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404; try_files $fastcgi_script_name =404;
include fastcgi_params; include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info; fastcgi_param PATH_INFO $path_info;
# fastcgi_param HTTPS on; fastcgi_param HTTPS on;
# Avoid sending the security headers twice fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; # Enable pretty urls
# Enable pretty urls
fastcgi_param front_controller_active true;
fastcgi_pass php-handler; fastcgi_pass php-handler;
fastcgi_intercept_errors on; fastcgi_intercept_errors on;
fastcgi_request_buffering off; fastcgi_request_buffering off;
fastcgi_max_temp_file_size 0;
} }
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) { # Serve static files
try_files $uri/ =404; location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
index index.php;
}
# Adding the cache control header for js, css and map files
# Make sure it is BELOW the PHP block
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
try_files $uri /index.php$request_uri; try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463"; # HTTP response headers borrowed from Nextcloud `.htaccess`
# Add headers to serve security related headers (It is intended to add_header Cache-Control "public, max-age=15778463$asset_immutable";
# have those duplicated to the ones above)
# Before enabling Strict-Transport-Security headers please read into
# this topic first.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
add_header Referrer-Policy "no-referrer" always; add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always; add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always; add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always; add_header X-XSS-Protection "1; mode=block" always;
access_log off; # Optional: Don't log access to assets
# Optional: Don't log access to assets
access_log off;
} }
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ { location ~ \.(otf|woff2?)$ {
try_files $uri /index.php$request_uri; try_files $uri /index.php$request_uri;
# Optional: Don't log access to other assets expires 7d; # Cache-Control policy borrowed from `.htaccess`
access_log off; access_log off; # Optional: Don't log access to assets
} }
# Rule borrowed from `.htaccess`
location /remote {
return 301 /remote.php$request_uri;
} }
location / {
try_files $uri $uri/ /index.php$request_uri;
}
##
## location / {
## rewrite ^ /index.php;
## }
##
## location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
## deny all;
## }
## location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
## deny all;
## }
##
## location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
## fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
## set $path_info $fastcgi_path_info;
## try_files $fastcgi_script_name =404;
## include fastcgi_params;
## fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
## fastcgi_param PATH_INFO $path_info;
## # fastcgi_param HTTPS on;
##
## # Avoid sending the security headers twice
## fastcgi_param modHeadersAvailable true;
##
## # Enable pretty urls
## fastcgi_param front_controller_active true;
## fastcgi_pass php-handler;
## fastcgi_intercept_errors on;
## fastcgi_request_buffering off;
## }
##
## location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
## try_files $uri/ =404;
## index index.php;
## }
##
## # Adding the cache control header for js, css and map files
## # Make sure it is BELOW the PHP block
## location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
## try_files $uri /index.php$request_uri;
## add_header Cache-Control "public, max-age=15778463";
## # Add headers to serve security related headers (It is intended to
## # have those duplicated to the ones above)
## # Before enabling Strict-Transport-Security headers please read into
## # this topic first.
## #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
## #
## # WARNING: Only add the preload option once you read about
## # the consequences in https://hstspreload.org/. This option
## # will add the domain to a hardcoded list that is shipped
## # in all major browsers and getting removed from this list
## # could take several months.
## add_header Referrer-Policy "no-referrer" always;
## add_header X-Content-Type-Options "nosniff" always;
## add_header X-Download-Options "noopen" always;
## add_header X-Frame-Options "SAMEORIGIN" always;
## add_header X-Permitted-Cross-Domain-Policies "none" always;
## add_header X-Robots-Tag "none" always;
## add_header X-XSS-Protection "1; mode=block" always;
##
## # Optional: Don't log access to assets
## access_log off;
## }
##
## location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
## try_files $uri /index.php$request_uri;
## # Optional: Don't log access to other assets
## access_log off;
## }
} }