commit d067d5f1f7e42fafd0c304a27ddaa99a87a3d076 Author: Chris Date: Thu Apr 3 22:57:52 2025 +0200 first commit diff --git a/.static-ips.yml b/.static-ips.yml new file mode 100644 index 0000000..084b3ba --- /dev/null +++ b/.static-ips.yml @@ -0,0 +1,18 @@ +# we use the last 256 block of ipv4 addresses in the traefik subnet to reserve some static ips +# use this file to manage the static ips used in the different compose.yml files + +# range that we will use for static ips is 10.255.239.0/24 +gluetun-arr: 10.255.239.1 +gluetun-bw: 10.255.239.2 +gluetun-qb: 10.255.239.3 +plex: 10.255.239.20 +tautulli: 10.255.239.21 +overseerr: 10.255.239.22 +firefly: 10.255.239.30 +firefly-importer: 10.255.239.31 + +# we use macvlan0 to connect to the local lan network. This lan has no internet access, so we can attach containers directly to it. +# the range that we will use for static ips is 192.168.2.240 to 192.168.2.254, i.e. 192.168.2.240/28 +# 192.168.2.240/28 range is excluded for DHCP on the DHCP server, so we can use it for static ips +# the range for the local lan network is 192.168.2.0/24 +syncthing: 192.168.2.241 diff --git a/audiobookshelf/audiobookshelf_jm.txt b/audiobookshelf/audiobookshelf_jm.txt new file mode 100644 index 0000000..381f39c --- /dev/null +++ b/audiobookshelf/audiobookshelf_jm.txt @@ -0,0 +1,59 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: audbkshelf +Username: audbkshelf +Disable Password: +Email: +Create New Primary Group: +# Denied action: MEASSAGE_CONTINUE +# Policy engine mode: any +# Click Create +# +# Creating Gitea provider and application +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# refer: https://docs.goauthentik.io/integrations/services/gitea/ +# +# Step 1: create gitea Provider +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Inside the Admin Interface navigate to Applications -> Providers +# Click Create +# In "New provider" screen, select "OAuth2/OpenID Provider" +# Click Next +# Name: gitea +# Authentication Flow: +# Authorization Flow: default-provider-authorization-explicit-consent (Authorize Application) +# Protocol settings: +# Client type: Confidential +# Client ID: PdTOme1WrQtgWQYa8fIfiedMyWBVKc9pqMz3qUa2 +# Client Secret: CNKd9D8AYvhDxzy4YKnU7hJoIHKgX3ADnmY5t6CtkVo2lseEwrnFLUSedZdmL55XECos7KpERlZ4S5GVUhbh2qG15DzbbYXuN9hv2sntsxWkQgRt7auCOJCJ7o8vxErI +# Redirect URIs: https://gitea.sthome.org/user/oauth2/authentik/callback +# Signing Key: Select any available key +# NB! Take note of the Client ID and Client Secret, you'll need to give them to Gitea in Step 3. +# Click Finish +# +# Step 2: create gitea Application +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# In the Admin Interface, go to Applications -> Applications -> Create +# On the "Create Application" screen enter: +# Name: gitea +# Slug: gitea-slug +# Group: +# Provider: gitea +# This is where you bind it to the previously created provider! +# Backchannel Providers: +# Policy Engine Mode: any +# UI Settings +# Launch URL: https://gitea.sthome.org +# If left empty, authentik will derive from gitea OpenID Connect Auto Discovery URL and add the port no (9000) +# Click Create +# +# Step 3: Configuring gitea to use authentik +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Browse to the Authentication Sources page at https://gitea.sthome.org/admin/auths +# Click "Add Authentication Source" +# Change the following fields: +# Authentication Type: OAuth2 +# Authentication Name: authentik +# OAuth2 Provider: OpenID Connect +# Client ID (Key): +# Client Secret: +# Icon URL: https://authentik.sthome.org/static/dist/assets/icons/icon.svg +# OpenID Connect Auto Discovery URL: https://authentik.sthome.org/application/o/gitea-slug/.well-known/openid-configuration +# If authentik and gitea is on the same internal network behind a reverse proxy, e.g. traefik, and are accessed (browsed to) from outside of this internal network then this OIDC Auto Discovery URL should be accessible externally and internally. The consequence is that the internal DNS should resolve to the external traefik entrypoint (port 443) with traefik routing it to authentik port 9000. (Otherwise accessing authentik on the internal network will require the OIDC Auto Discovery URL to include port 9000, which will cause the redirect to authentik (from external network) to fail.) Refer to: https://www.reddit.com/r/Authentik/comments/1ggimab/authentik_with_traefik_in_docker/ +# Additional Scopes: email profile +# Click "Add Authentication Source" +# Your Gitea login page should now have a Sign in With followed by the authentik logo which you can click on to sign-in to Gitea with Authentik creds. +# +# Step 4 (optional Claims for authorization management) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This step is optional and shows how to set claims to control the permissions of users in gitea by adding them to groups. +# +# Define Groups: +# The following groups will be used: +# - gituser for normal Gitea users. +# - gitadmin for Gitea users with administrative permissions. +# - gitrestricted for restricted Gitea users. +# Users who are in none of these groups will not be able to log in to gitea. +# +# In the authentik Admin Interface, go to Directory -> Groups -> Create +# Name: gituser +# Leave other settings untouched. +# Click Create +# Repeat for gitadmin and gitrestricted +# You can add Members to the groups now or anytime later. +# +# Adding user to a group (from the User screen): +# In the authentik Admin Interface, go to Directory -> Users +# Select the user (click on the listed Name) +# Click the "Groups" tab at the top +# Click "Add to existing group" +# Click on "+" and select the desired groups +# Click "Add" twice +# +# Adding user to a group (from the Group screen): +# In the authentik Admin Interface, go to Directory -> Groups +# Select the group (click on the listed Name) +# Click the "Users" tab at the top +# Click "Add to existing user" +# Click on "+" and select the desired user +# Click "Add" twice + +# Create Custom Property Mapping: +# In the authentik Admin Interface, go to Customization -> Property Mappings -> Create +# On "New property mapping" screen, "Select Type" tab, +# Select Scope Mapping, click Next +# On "Create Scope Mapping" tab, enter: +# Name: authentik gitea OAuth Mapping: OpenID 'gitea' +# Scope name: gitea +# Description: +# Expression: enter the following text lines between --- snip ---: +# --- snip --- +gitea_claims = {} +if request.user.ak_groups.filter(name="gituser").exists(): + gitea_claims["gitea"]= "user" +if request.user.ak_groups.filter(name="gitadmin").exists(): + gitea_claims["gitea"]= "admin" +if request.user.ak_groups.filter(name="gitrestricted").exists(): + gitea_claims["gitea"]= "restricted" + +return gitea_claims +# --- snip --- +# +# Add the custom Property Mapping to the Gitea Provider: +# In authentik, go to Applications -> Providers +# Edit gitea provider (click pencil icon under Actions in gitea row) +# Expand the Advanced protocol settings and select the following Mappings (hold ctrl key and select, i.e. left click with mouse): +# authentik default OAuth Mapping: OpenID 'email' +# authentik default OAuth Mapping: OpenID 'profile' +# authentik default OAuth Mapping: OpenID 'openid' +# authentik gitea OAuth Mapping: OpenID 'gitea' +# Click Update +# +# Configure Gitea to use the new claims: +# In .gitea.env file, set environment variable as follows: + GITEA__oauth2_client__ENABLE_AUTO_REGISTRATION=true +# +# Navigate to the Authentication Sources page at https://gitea.sthome.org/admin/auths and edit the authentik Authentication Source (click on pencil icon) +# Change the following fields +# Additional Scopes: email profile gitea +# Required Claim Name: gitea +# Required Claim Value: +# Claim name providing group names for this source. (Optional): gitea +# Group Claim value for administrator users. (Optional - requires claim name above): admin +# Group Claim value for restricted users. (Optional - requires claim name above): restricted +# Click "Update Authentication Source" +# +# Users without any of the defined groups should no longer be able to log in. Users of the group gitadmin should have administrative privileges, and users in the group gitrestricted should be restricted. \ No newline at end of file diff --git a/authentik/cp2nas.ps1 b/authentik/cp2nas.ps1 new file mode 100644 index 0000000..c76fd40 --- /dev/null +++ b/authentik/cp2nas.ps1 @@ -0,0 +1,135 @@ +############### CONST ############## +$destJailDir="/mnt/SSD1/docker/" +$stacksfolder="stacks/" +$datafolder="data/" +$destStacks=$destJailDir+$stacksfolder +$destData=$destJailDir+$datafolder +$destTraefikRulesDir=$destData+"traefik/rules/" +$destTraefikUsersDir=$destData+"traefik/users/" +############### MAIN ############### +# main function +# +$Main = +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + [Parameter(Mandatory=$false)] + [string[]] $apps + ) + $applist=[System.Collections.Generic.List[object]]::new() + If($PSBoundParameters.ContainsKey("apps")) { + foreach ($appname in $apps) + { + if ($appname.Contains('*')) { + $wclist=Get-ChildItem $appname -Directory | ForEach-Object { $_.Name } + # if wildcard is specified, we only add folders with a 'stacks' subfolder + foreach ($wcname in $wclist) { + if ((Test-Path -Path "$wcname\stacks")) { + $applist.Add($wcname) + } + } + } + else { + # here we don't have to check for a 'stacks' subfolder as the user specified appname explicitly + $applist.Add($appname) + } + } + # remove duplicates + $uniqlist=$applist | Sort-Object -Unique + foreach ($appname in $uniqlist) + { + copyfolder $destHost $appname "$appname\" + } + } + else { + # we're in the app subfolder, so only one stacks folder to copy + $appname="$pwd".Split("\\")[-1] + copyfolder $destHost $appname ".\" + } +} +####################################################################### +# copies specified folder to data folder on truenas +# +Function copytosubfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $folder, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $subfolder, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destdir + ) + if ((Test-Path -Path "$srcdir")) { + Write-Host "$date# pscp -P 22 -r ""$srcdir\*.*"" root@${destHost}:""${destdir}""" -ForegroundColor Green + Write-Host "Copying to ${destHost}:""${destJailDir}" -NoNewline + Write-Host "${folder}" -ForegroundColor Cyan -NoNewline + Write-Host "${subfolder}" -ForegroundColor DarkYellow -NoNewline + Write-Host """:" + pscp -P 22 -r "$srcdir\*.*" root@${destHost}:""${destdir}"" + } +} +####################################################################### +# copies specified app's stacks and traefik-rules subfolders to truenas +# +Function copyfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $subfolder, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir + ) + $srcStacksDir=$srcdir+"stacks" + $srcTraefikRulesDir=$srcdir+"traefik-rules" + $srcTraefikUsersDir=$srcdir+"traefik-users" + if (-Not(Test-Path -Path $srcStacksDir)) { + Write-Host "Source path doesn't exist: ""$PSScriptRoot\$srcStacksDir\*.*"". No files copied!" -ForegroundColor Red + Write-Host "Usage: in app folder : ./cp2nas DEST|IP" + Write-Host " in app parent folder: ./cp2nas DEST|IP app1, app2, app3, ..." + Write-Host " in app parent folder: ./cp2nas DEST|IP *" + Write-Host " in app parent folder: ./cp2nas DEST|IP wcstring1, wcstring2, ..." + return + } + $destAppStacksDir=$destStacks+$subfolder+"/" + $date=Get-Date -format "yyyy-MM-ddTHH:mm:ss" + #Write-Host "$date# pscp -P 22 -r ""$srcStacksDir\*.*"" root@${destHost}:""${destAppStacksDir}""" -ForegroundColor Green + #Write-Host "Copying to ${destHost}:""${destStacks}" -NoNewline + #Write-Host "${subfolder}/" -ForegroundColor DarkYellow -NoNewline + #Write-Host """:" + #pscp -P 22 -r "$srcStacksDir\*.*" root@${destHost}:""${destAppStacksDir}"" + copytosubfolder $destHost "${stacksfolder}" "${subfolder}" "${srcStacksDir}" "${destAppStacksDir}" + + # check for data dir destinations and copy + copytosubfolder $destHost "${stacksfolder}" "traefik/rules/" "${srcTraefikRulesDir}" "${destTraefikRulesDir}" + copytosubfolder $destHost "${stacksfolder}" "traefik/users/" "${srcTraefikUsersDir}" "${destTraefikUsersDir}" + +} + +################################### +& $Main @Args \ No newline at end of file diff --git a/authentik/stacks/.env b/authentik/stacks/.env new file mode 100644 index 0000000..724043f --- /dev/null +++ b/authentik/stacks/.env @@ -0,0 +1,60 @@ +################################################################ +# .env +# When both env_file and environment are set for a service, values set by environment have precedence. +# https://docs.docker.com/compose/environment-variables/envvars-precedence/ +# +# CANNOT MIX ARRAYS (KEY: VAL) AND MAPS (KEY=VAL) +# Ex: Cannot have .ENV var as TZ=US and then a var here as DB_ENGINE: sqlite, has to be DB_ENGINE=sqlite +# Otherwise unexpected type map[string]interface {} occurs +# https://github.com/docker/compose/issues/11567 +# +################################################################ +APPLICATION_NAME=authentik +DOCKERDIR=/mnt/SSD1/docker/ +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +PUID=3014 +PGID=3013 +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org +WEBUI_PORT=9000 + +################################################################ +# Authentik (https://docs.goauthentik.io/docs/) +# Environment Variables (https://docs.goauthentik.io/docs/installation/configuration) +################################################################ +POSTGRES_DB_PORT=5432 +POSTGRES_PASSWORD_FILE=/run/secrets/authentik_postgresql_password +POSTGRES_USER_FILE=/run/secrets/authentik_postgresql_username +POSTGRES_DB_FILE=/run/secrets/authentik_postgresql_database + +AUTHENTIK_POSTGRESQL__NAME_FILE=file:///run/secrets/authentik_postgresql_database +AUTHENTIK_POSTGRESQL__USER_FILE=file:///run/secrets/authentik_postgresql_username +AUTHENTIK_POSTGRESQL__PASSWORD_FILE=file:///run/secrets/authentik_postgresql_password +AUTHENTIK_DISABLE_STARTUP_ANALYTICS=true +AUTHENTIK_DISABLE_UPDATE_CHECK=false +AUTHENTIK_ERROR_REPORTING__ENABLED=false +AUTHENTIK_LOG_LEVEL=info # debug, info, warning, error, trace +AUTHENTIK_SECRET_KEY_FILE=file:///run/secrets/authentik_secret_key # openssl rand 60 | base64 -w 0 +AUTHENTIK_COOKIE_DOMAIN=${DOMAINNAME} +AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: 127.0.0.0/8, 10.0.0.0/24, 172.16.0.0/12, 192.168.2.0/124, fe80::/10, ::1/128 + +AUTHENTIK_EMAIL__PORT=25 +AUTHENTIK_EMAIL__USE_TLS=false +AUTHENTIK_EMAIL__USE_SSL=false +AUTHENTIK_EMAIL__TIMEOUT=10 +AUTHENTIK_EMAIL__HOST_FILE=file:///run/secrets/smtp_host +AUTHENTIK_EMAIL__USERNAME_FILE=file:///run/secrets/smtp_username +AUTHENTIK_EMAIL__PASSWORD_FILE=file:///run/secrets/smtp_password +AUTHENTIK_EMAIL__FROM_FILE=file:///run/secrets/smtp_from + +################################################################ +# GeoIP ( https://github.com/maxmind/geoipupdate) +# Environment Variables (https://github.com/maxmind/geoipupdate/blob/main/doc/docker.md) +################################################################ +GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN" # Space seperated +GEOIPUPDATE_FREQUENCY=8 # Frequency to check for updates, in hours +GEOIPUPDATE_ACCOUNT_ID_FILE=/run/secrets/geoip_acccount_id +GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/geoip_license_key \ No newline at end of file diff --git a/authentik/stacks/.postgresql.env b/authentik/stacks/.postgresql.env new file mode 100644 index 0000000..0d95871 --- /dev/null +++ b/authentik/stacks/.postgresql.env @@ -0,0 +1,11 @@ + +PUID=70 +PGID=70 +TZ=${TZ} + +POSTGRES_DB_PORT=${POSTGRES_DB_PORT} +POSTGRES_DB_FILE=${POSTGRES_DB_FILE} +POSTGRES_USER_FILE=${POSTGRES_USER_FILE} +POSTGRES_PASSWORD_FILE=${POSTGRES_PASSWORD_FILE} + + diff --git a/authentik/stacks/.server.env b/authentik/stacks/.server.env new file mode 100644 index 0000000..bb670d5 --- /dev/null +++ b/authentik/stacks/.server.env @@ -0,0 +1,13 @@ + +TZ=${TZ} + +AUTHENTIK_POSTGRESQL__NAME=${AUTHENTIK_POSTGRESQL__NAME_FILE} +AUTHENTIK_POSTGRESQL__USER=${AUTHENTIK_POSTGRESQL__USER_FILE} +AUTHENTIK_POSTGRESQL__PASSWORD=${AUTHENTIK_POSTGRESQL__PASSWORD_FILE} +AUTHENTIK_DISABLE_STARTUP_ANALYTICS=${AUTHENTIK_DISABLE_STARTUP_ANALYTICS} +AUTHENTIK_DISABLE_UPDATE_CHECK=${AUTHENTIK_DISABLE_UPDATE_CHECK} +AUTHENTIK_ERROR_REPORTING__ENABLED=${AUTHENTIK_ERROR_REPORTING__ENABLED} +AUTHENTIK_LOG_LEVEL=${AUTHENTIK_LOG_LEVEL} +AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY_FILE} +AUTHENTIK_COOKIE_DOMAIN=${DOMAINNAME} +# AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS=${AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS} diff --git a/authentik/stacks/.socket-proxy.env b/authentik/stacks/.socket-proxy.env new file mode 100644 index 0000000..97691c1 --- /dev/null +++ b/authentik/stacks/.socket-proxy.env @@ -0,0 +1,36 @@ +# +# environment variables for socket-proxy +# + +LOG_LEVEL=info # debug,info,notice,warning,err,crit,alert,emerg + +## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.). +### 0 to revoke access. +### 1 to grant access. +## Granted by Default +EVENTS=1 +PING=1 +VERSION=1 +## Revoked by Default +### Security critical +AUTH=0 +SECRETS=0 +POST=1 # Watchtower +### Not always needed +BUILD=0 +COMMIT=0 +CONFIGS=0 +CONTAINERS=1 # Traefik, portainer, etc. +DISTRIBUTION=0 +EXEC=0 +IMAGES=1 # Portainer +INFO=1 # Portainer +NETWORKS=1 # Portainer +NODES=0 +PLUGINS=0 +SERVICES=1 # Portainer +SESSION=0 +SWARM=0 +SYSTEM=0 +TASKS=1 # Portainer +VOLUMES=1 # Portainer \ No newline at end of file diff --git a/authentik/stacks/.worker.env b/authentik/stacks/.worker.env new file mode 100644 index 0000000..c622ee2 --- /dev/null +++ b/authentik/stacks/.worker.env @@ -0,0 +1,21 @@ + +TZ=${TZ} + +AUTHENTIK_POSTGRESQL__NAME=${AUTHENTIK_POSTGRESQL__NAME_FILE} +AUTHENTIK_POSTGRESQL__USER=${AUTHENTIK_POSTGRESQL__USER_FILE} +AUTHENTIK_POSTGRESQL__PASSWORD=${AUTHENTIK_POSTGRESQL__PASSWORD_FILE} +AUTHENTIK_DISABLE_STARTUP_ANALYTICS=${AUTHENTIK_DISABLE_STARTUP_ANALYTICS} +AUTHENTIK_DISABLE_UPDATE_CHECK=${AUTHENTIK_DISABLE_UPDATE_CHECK} +AUTHENTIK_ERROR_REPORTING__ENABLED=${AUTHENTIK_ERROR_REPORTING__ENABLED} +AUTHENTIK_LOG_LEVEL=${AUTHENTIK_LOG_LEVEL} +AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY_FILE} +AUTHENTIK_COOKIE_DOMAIN=${DOMAINNAME} + +AUTHENTIK_EMAIL__HOST=${AUTHENTIK_EMAIL__HOST_FILE} +AUTHENTIK_EMAIL__PORT=${AUTHENTIK_EMAIL__PORT} +AUTHENTIK_EMAIL__USERNAME=${AUTHENTIK_EMAIL__USERNAME_FILE} +AUTHENTIK_EMAIL__PASSWORD=${AUTHENTIK_EMAIL__PASSWORD_FILE} +AUTHENTIK_EMAIL__USE_TLS=${AUTHENTIK_EMAIL__USE_TLS} +AUTHENTIK_EMAIL__USE_SSL=${AUTHENTIK_EMAIL__USE_SSL} +AUTHENTIK_EMAIL__TIMEOUT=${AUTHENTIK_EMAIL__TIMEOUT} +AUTHENTIK_EMAIL__FROM=${AUTHENTIK_EMAIL__FROM_FILE} diff --git a/authentik/stacks/compose.yml b/authentik/stacks/compose.yml new file mode 100644 index 0000000..9333896 --- /dev/null +++ b/authentik/stacks/compose.yml @@ -0,0 +1,248 @@ +############################################################### +# ------------------------------ +# -- authentik (Identity Provider / SSO) +# -- Updated/Created 2024-July-02 +# Authentik configuration: https://docs.goauthentik.io/docs/installation/configuration +# ------------------------------ +name: authentik # Project Name + +############################################################### +# Networks +############################################################### +networks: + socket_proxy: + driver: bridge + driver_opts: + com.docker.network.bridge.name: "br-authentik_sx" + traefik-net: + external: true + authentik-net: + external: true + +############################################################### +# Docker Secrets +# Owner (default): root:root +# Recommend Set Owner to match container user Example: UID=1100, GID=1100 +# Permissions of files & directory on host to: 0400 (-r--) +############################################################### +secrets: + ## Authentik + authentik_postgresql_database: + file: ${SECRETSDIR}/authentik_postgresql_database + authentik_postgresql_username: + file: ${SECRETSDIR}/authentik_postgresql_username + authentik_postgresql_password: + file: ${SECRETSDIR}/authentik_postgresql_password + authentik_secret_key: + file: ${SECRETSDIR}/authentik_secret_key + smtp_username: + file: ${SECRETSDIR}/smtp_username + smtp_password: + file: ${SECRETSDIR}/smtp_password + ## GeoIP + geoip_account_id: + file: ${SECRETSDIR}/geoip_account_id + geoip_license_key: + file: ${SECRETSDIR}/geoip_license_key + +############################################################################## +services: + # Use the embedded outpost (2021.8.1+) instead of the seperate Forward Auth / Proxy Provider container + server: + image: ghcr.io/goauthentik/server:latest + restart: unless-stopped + env_file: .server.env + environment: + - AUTHENTIK_REDIS__HOST=authentik_redis + - AUTHENTIK_POSTGRESQL__HOST=authentik_postgresql + command: server + user: ${PUID}:${PGID} + depends_on: + postgresql: + condition: service_healthy + redis: + condition: service_healthy + networks: + socket_proxy: {} + authentik-net: {} + traefik-net: + aliases: ["authentik_server"] # keep the same as forwardAuth address (hostname) in traefik middlewares "forwardAuth-authentik.yml" + secrets: + - authentik_postgresql_database + - authentik_postgresql_username + - authentik_postgresql_password + - authentik_secret_key + volumes: + - "${DATADIR}/appdata/media:/media" + - "${DATADIR}/appdata/custom-templates:/templates" + - "${DATADIR}/appdata/geoip/data:/geoip" + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + ## HTTP Routers + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)" + ## Individual Application forwardAuth regex (catch any subdomain using individual application forwardAuth) + - "traefik.http.routers.${APPLICATION_NAME}-output-rtr.rule=HostRegexp(`{subdomain:[a-z0-9-]+}.${DOMAINNAME}`) && PathPrefix(`/outpost.goauthentik.io/`)" + ## HTTP Services + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + - "traefik.http.services.${APPLICATION_NAME}-svc.loadBalancer.server.port=${WEBUI_PORT}" + + worker: + image: ghcr.io/goauthentik/server:latest + restart: unless-stopped + env_file: .worker.env + environment: + - DOCKER_HOST=tcp://authentik_socket-proxy:2375 # Use this if you have Socket Proxy enabled. + - AUTHENTIK_REDIS__HOST=authentik_redis + - AUTHENTIK_POSTGRESQL__HOST=authentik_postgresql + user: ${PUID}:${PGID} + command: worker + depends_on: + postgresql: + condition: service_healthy + redis: + condition: service_healthy + networks: + - authentik-net + - socket_proxy + secrets: + - authentik_postgresql_database + - authentik_postgresql_username + - authentik_postgresql_password + - authentik_secret_key + - smtp_username + - smtp_password + volumes: + - "${DATADIR}/appdata/media:/media" + - "${DATADIR}/appdata/custom-templates:/templates" + - "${DATADIR}/appdata/geoip/data:/geoip" + # - /var/run/docker.sock:/var/run/docker.sock # Uncomment if NOT using socket-proxy + #- "${DATADIR}/appdata/traefik/cert_export:/certs:ro" # If NOT using reverse proxy, manually map in certificates + + postgresql: + image: postgres:16-alpine + shm_size: 128mb # https://hub.docker.com/_/postgres + restart: unless-stopped + env_file: .postgresql.env + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + networks: + authentik-net: + aliases: ["authentik_postgresql"] + volumes: + - "${DATADIR}/pgdata:/var/lib/postgresql/data" + secrets: + - authentik_postgresql_database + - authentik_postgresql_username + # Generate the password with openssl rand 36 | base64 -w 0 + - authentik_postgresql_password + + redis: + image: docker.io/library/redis:alpine + command: --save 60 1 --loglevel warning + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "redis-cli ping | grep PONG"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 3s + networks: + authentik-net: + aliases: ["authentik_redis"] + volumes: + - "${DATADIR}/appdata/redis/data:/data" + +# geoipupdate: +# image: ghcr.io/maxmind/geoipupdate:latest +# container_name: geoipupdate +# restart: unless-stopped +# user: ${PUID}:${PGID} +# volumes: +# - "${DATADIR}/appdata/geoip/data:/usr/share/GeoIP" +# networks: +# - authentik-net +# secrets: +# - geoip_account_id +# - geoip_license_key +# environment: +# - GEOIPUPDATE_EDITION_IDS +# - GEOIPUPDATE_FREQUENCY +# - GEOIPUPDATE_ACCOUNT_ID_FILE +# - GEOIPUPDATE_LICENSE_KEY_FILE +# - TZ + + socket-proxy: + image: tecnativa/docker-socket-proxy:0.2.0 #0.1.2 + restart: unless-stopped + env_file: .socket-proxy.env + security_opt: + - no-new-privileges=true + networks: + socket_proxy: + aliases: ["authentik_socket-proxy"] + privileged: true # true for VM. false for unprivileged LXC container. +# ports: +# - "127.0.0.1:2375:2375" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + + whoami: + image: traefik/whoami:latest +# container_name: whoami + restart: unless-stopped + security_opt: + - no-new-privileges=true + networks: + - traefik-net + environment: + - TZ + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + ## HTTP Routers + - "traefik.http.routers.whoami-rtr.rule=Host(`whoami.${DOMAINNAME}`)" + + whoami-individual: + image: traefik/whoami:latest + restart: unless-stopped + security_opt: + - no-new-privileges:true + depends_on: + - server + - worker + networks: + - traefik-net + environment: + - TZ + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + ## HTTP Routers + - "traefik.http.routers.whoami-individual-rtr.rule=Host(`whoami-individual.${DOMAINNAME}`)" + ## attach AUTHENTIK forwardauth middlewares to router; comment out if not using authentik + - "traefik.http.routers.whoami-individual-rtr.middlewares=forwardAuth-authentik@file" + + whoami-catchall: + image: traefik/whoami:latest + restart: unless-stopped + security_opt: + - no-new-privileges:true + depends_on: + - server + - worker + networks: + - traefik-net + environment: + - TZ + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + ## HTTP Routers + - "traefik.http.routers.whoami-catchall-rtr.rule=Host(`whoami-catchall.${DOMAINNAME}`)" + ## attach AUTHENTIK forwardauth middlewares to router; comment out if not using authentik + - "traefik.http.routers.whoami-catchall-rtr.middlewares=forwardAuth-authentik@file" diff --git a/authentik/traefik-rules/forwardAuth-authentik.yml b/authentik/traefik-rules/forwardAuth-authentik.yml new file mode 100644 index 0000000..6af7219 --- /dev/null +++ b/authentik/traefik-rules/forwardAuth-authentik.yml @@ -0,0 +1,30 @@ +################################################################ +# Middlewares (https://github.com/htpcBeginner/docker-traefik/blob/master/appdata/traefik2/rules/cloudserver/middlewares.yml) +# 2024 update: https://github.com/htpcBeginner/docker-traefik/tree/master/appdata/traefik3/rules/hs +# https://www.smarthomebeginner.com/traefik-docker-compose-guide-2022/ +# +# Dynamic configuration +################################################################ +http: + middlewares: + ################################################################ + # Forward Authentication - OAUTH / 2FA + ################################################################ + # + # https://github.com/goauthentik/authentik/issues/2366 + forwardAuth-authentik: + forwardAuth: + address: "http://authentik_server:9000/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/authentik/try-this-out.txt b/authentik/try-this-out.txt new file mode 100644 index 0000000..c6c4ac8 --- /dev/null +++ b/authentik/try-this-out.txt @@ -0,0 +1,47 @@ +# Seems this is for forward-auth only + +# https://docs.goauthentik.io/docs/add-secure-apps/providers/proxy/server_traefik +# +services: + traefik: + image: traefik:v3.0 + container_name: traefik + volumes: + - /var/run/docker.sock:/var/run/docker.sock + ports: + - 80:80 + command: + - "--api" + - "--providers.docker=true" + - "--providers.docker.exposedByDefault=false" + - "--entrypoints.web.address=:80" + + authentik-proxy: + image: ghcr.io/goauthentik/proxy + ports: + - 9000:9000 + - 9443:9443 + environment: + AUTHENTIK_HOST: https://your-authentik.tld + AUTHENTIK_INSECURE: "false" + AUTHENTIK_TOKEN: token-generated-by-authentik + # Starting with 2021.9, you can optionally set this too + # when authentik_host for internal communication doesn't match the public URL + # AUTHENTIK_HOST_BROWSER: https://external-domain.tld + labels: + traefik.enable: true + traefik.port: 9000 + traefik.http.routers.authentik.rule: Host(`app.company`) && PathPrefix(`/outpost.goauthentik.io/`) + # `authentik-proxy` refers to the service name in the compose file. + traefik.http.middlewares.authentik.forwardauth.address: http://authentik-proxy:9000/outpost.goauthentik.io/auth/traefik + traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: true + traefik.http.middlewares.authentik.forwardauth.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 + restart: unless-stopped + + whoami: + image: containous/whoami + labels: + traefik.enable: true + traefik.http.routers.whoami.rule: Host(`app.company`) + traefik.http.routers.whoami.middlewares: authentik@docker + restart: unless-stopped \ No newline at end of file diff --git a/calibre/calibre_jm.txt b/calibre/calibre_jm.txt new file mode 100644 index 0000000..a9160dc --- /dev/null +++ b/calibre/calibre_jm.txt @@ -0,0 +1,61 @@ +# https://github.com/linuxserver/docker-calibre/pkgs/container/calibre + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: calibre +Username: calibre +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +calibre UID: 3032 +calibre GID: 3031 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*calibre" +# create following datasets if not present +zfs create SSD1/docker/data/calibre +zfs create SSD1/docker/data/calibre/config +chown -R calibre:calibre /mnt/SSD1/docker/data/calibre + +Create folders +-------------- +mkdir -p /mnt/SSD1/docker/stacks/calibre/secrets + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in calibre folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/calibre/ + +Create secrets +-------------- +cd /mnt/SSD1/docker/stacks/calibre/secrets +echo -n 'your_calibre_password' > /mnt/SSD1/docker/stacks/calibre/secrets/calibre_password +chown -R calibre:calibre /mnt/SSD1/docker/stacks/calibre/secrets +chmod -R 400 /mnt/SSD1/docker/stacks/calibre/secrets + +Migrating data from old calibre (source) to newly installed one (target) +------------------------------------------------------------------------ +# stop old/source calibre media server +heavyscript app --stop calibre +# verify on Truenas -> Apps that calibre has stopped +# stop new/target calibre media server (if it was started) +# on Dockge, select calibre and click stop +# copy the source to target folder: +cp -pr /mnt/stpool1/apps/calibre/. /mnt/SSD1/docker/data/calibre/config/ +chown -R calibre:calibre /mnt/SSD1/docker/data/calibre/config + + + + + diff --git a/calibre/stacks/.calibre.env b/calibre/stacks/.calibre.env new file mode 100644 index 0000000..2b311cc --- /dev/null +++ b/calibre/stacks/.calibre.env @@ -0,0 +1,18 @@ + +PUID=${PUID} +PGID=${MEDIA_GID} # we assign media gid to process gid to enable to access media folders +TZ=${TZ} +CUSTOM_USER=admin +FILE__PASSWORD=/run/secrets/calibre_password +CLI_ARGS= + +CUSTOM_PORT=8080 +CUSTOM_HTTPS_PORT=8181 +SUBFOLDER= +TITLE="Calibre" +FM_HOME="/config" +START_DOCKER= +DRINODE= +LC_ALL= +NO_DECOR= +NO_FULL= diff --git a/calibre/stacks/.env b/calibre/stacks/.env new file mode 100644 index 0000000..58c27c6 --- /dev/null +++ b/calibre/stacks/.env @@ -0,0 +1,21 @@ + +APPLICATION_NAME=calibre +MEDIADIR=/mnt/stpool1/NData1/Media +DOCKERDIR=/mnt/SSD1/docker/ +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +CT_DOWNLOADS=/Downloads +CT_MEDIA=/Media +DOMAINNAME=sthome.org + + +PUID=3032 +PGID=3031 +MEDIA_GID=3017 + +TZ=Africa/Johannesburg + +WEBUI_PORT=8080 +WEBUI_SECPORT=8181 diff --git a/calibre/stacks/compose.yml b/calibre/stacks/compose.yml new file mode 100644 index 0000000..eea0bcf --- /dev/null +++ b/calibre/stacks/compose.yml @@ -0,0 +1,63 @@ +name: calibre + +secrets: + calibre_password: + file: ${SECRETSDIR}/calibre_password + +networks: + traefik-net: + external: true + +services: + calibre: + image: lscr.io/linuxserver/calibre:latest + env_file: .calibre.env + hostname: calibre + group_add: + - "${PGID}" + security_opt: + - seccomp:unconfined #optional + networks: + - traefik-net + volumes: + - "${DATADIR}/config:/config" + - "${MEDIADIR}/Books:/Books" + restart: unless-stopped + secrets: + - calibre_password + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http middlewares + # --------------------------- + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.permanent=true" + # + # http services + # ------------- + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http routers + # ------------ + # limit router to web ":80" entrypoint (Note: web entrypoint http requests are globally redirected to websecure router in traefik.yml) + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=${APPLICATION_NAME}-https-redirect" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # set router to be dedicated to secure requests only for the host specified in match criteria + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=sthomeresolver" + ## attach AUTHENTIK forwardauth middlewares to router; comment out if not using authentik + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=forwardAuth-authentik@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" diff --git a/certbot/stacks/compose.yml b/certbot/stacks/compose.yml new file mode 100644 index 0000000..87803f3 --- /dev/null +++ b/certbot/stacks/compose.yml @@ -0,0 +1,11 @@ +services: + certbot: + stdin_open: true + tty: true + container_name: certbot + volumes: + - /etc/letsencrypt:/etc/letsencrypt + - /var/lib/letsencrypt:/var/lib/letsencrypt + image: certbot/certbot + command: certonly +networks: {} diff --git a/cloudflareddns/cloudflareddns_jm.txt b/cloudflareddns/cloudflareddns_jm.txt new file mode 100644 index 0000000..365bf10 --- /dev/null +++ b/cloudflareddns/cloudflareddns_jm.txt @@ -0,0 +1,71 @@ +# https://hotio.dev/containers/cloudflareddns/ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: cloudflareddns +Username: cfddns +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +cfddns UID: 3033 +cfddns GID: 3032 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*cloudflareddns" +# create following dataset if not present +zfs create SSD1/docker/data/cloudflareddns/config +chown -R cfddns:cfddns /mnt/SSD1/docker/data/cloudflareddns + +Create folders +-------------- +mkdir -p /mnt/SSD1/docker/stacks/cloudflareddns/secrets + +Create secrets (unfortunately, cloudflareddns doesn't support secrets, so apply the secret values in the .env file) +------------------------------------------------------------------------------------------------------------------- +cd /mnt/SSD1/docker/stacks/cloudflareddns/secrets +echo -n 'your_cf_email' > /mnt/SSD1/docker/stacks/cloudflareddns/secrets/cloudflareddns_cf_user +# it is assumed that your api token has all zones in scope: +# we use a scoped api token: +echo -n 'your_cf_api_token' > /mnt/SSD1/docker/stacks/cloudflareddns/secrets/cloudflareddns_cf_api_token +# create secret by concatenating hosts/domains in scope; separate with semicolons (as per hotio guide) +echo -n 'your_cf_1st_host;your_cf_2nd_host' > /mnt/SSD1/docker/stacks/cloudflareddns/secrets/cloudflareddns_cf_hosts +# create secret by concatenating zone ids; separate with semicolons +echo -n 'your_cf_1st_zone_id;your_cf_2nd_zone_id' > /mnt/SSD1/docker/stacks/cloudflareddns/secrets/cloudflareddns_cf_zones + +# restrict access +cd /mnt/SSD1/docker/stacks/cloudflareddns +chown -R cfddns:cfddns secrets/ +chmod -R 400 secrets/ + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in cloudflareddns folder, enter: +./cp2nas 192.168.2.2 +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/cloudflareddns/ +# This should copy stacks folder to /mnt/SSD1/docker/stacks/cloudflareddns + +Migrating data from old cloudflareddns media server (source) to newly installed one (target) +---------------------------------------------------------------------------------- +# Stop old/source cloudflareddns media server +heavyscript app --stop cloudflareddns +# Stop new/target cloudflareddns media server +# On Dockge, select cloudflareddns and click stop +# Copy the source config to target folder: +cp -vpr /mnt/stpool1/apps/cloudflareddns/* /mnt/SSD1/docker/data/cloudflareddns/config/ +chown -R cfddns:cfddns /mnt/SSD1/docker/data/cloudflareddns/config +chmod -R 600 /mnt/SSD1/docker/data/cloudflareddns/config/ + + + + + diff --git a/cloudflareddns/stacks/.cloudflareddns.env b/cloudflareddns/stacks/.cloudflareddns.env new file mode 100644 index 0000000..a2270dc --- /dev/null +++ b/cloudflareddns/stacks/.cloudflareddns.env @@ -0,0 +1,25 @@ +# +# environment variables for cloudflareddns +# + +PUID=3033 +PGID=3032 +UMASK=002 +TZ=Africa/Johannesburg +INTERVAL=300 +DETECTION_MODE=dig-whoami.cloudflare +LOG_LEVEL=3 +CF_APIKEY= +CF_APITOKEN_ZONE= +CF_RECORDTYPES=A;A + +# cloudflareddns doesn't support secrets +#CF_USER_FILE=${CFDDNS_CF_USER_FILE} +#CF_APITOKEN_FILE=${CFDDNS_CF_API_TOKEN_FILE} +#CF_HOSTS_FILE=${CFDDNS_CF_HOSTS_FILE} +#CF_ZONES_FILE=${CFDDNS_CF_ZONES_FILE} + +CF_USER=${CFDDNS_CF_USER} +CF_APITOKEN=${CFDDNS_CF_API_TOKEN} +CF_HOSTS=${CFDDNS_CF_HOSTS} +CF_ZONES=${CFDDNS_CF_ZONES} diff --git a/cloudflareddns/stacks/.env b/cloudflareddns/stacks/.env new file mode 100644 index 0000000..71af963 --- /dev/null +++ b/cloudflareddns/stacks/.env @@ -0,0 +1,26 @@ +# +# values to be used for substitution by docker compose in compose.yml AND .*.env files +# + +APPLICATION_NAME=cloudflareddns +DOCKERDIR=/mnt/SSD1/docker/ +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org + +# secrets +#CFDDNS_CF_USER_FILE=/run/secrets/cloudflareddns_cf_user +#CFDDNS_CF_API_TOKEN_FILE=/run/secrets/cloudflareddns_cf_api_token +#CFDDNS_CF_HOSTS_FILE=/run/secrets/cloudflareddns_cf_hosts +#CFDDNS_CF_ZONES_FILE=/run/secrets/cloudflareddns_cf_zones + +# cloudflareddns doesn't support secrets, so we have to put it in the clear +CFDDNS_CF_USER=stuurmcp@telkomsa.net +CFDDNS_CF_API_TOKEN=cUB02hE0GYC5VnydAHSbPckRrIZ0eN3pJKoCgnIb +CFDDNS_CF_HOSTS=sthome.org;stokvis.co.za +CFDDNS_CF_ZONES=d4d41ece44b6eea658b4638b41c4b425;2d4f09713fb66fd7e03eea62d1474b98 + + + diff --git a/cloudflareddns/stacks/compose.yml b/cloudflareddns/stacks/compose.yml new file mode 100644 index 0000000..bc2234e --- /dev/null +++ b/cloudflareddns/stacks/compose.yml @@ -0,0 +1,33 @@ +# cloudflareddns doesn't support secrets +#secrets: +# cloudflareddns_cf_user: +# file: ${SECRETSDIR}/cloudflareddns_cf_user +# cloudflareddns_cf_api_token: +# file: ${SECRETSDIR}/cloudflareddns_cf_api_token +# cloudflareddns_cf_hosts: +# file: ${SECRETSDIR}/cloudflareddns_cf_hosts +# cloudflareddns_cf_zones: +# file: ${SECRETSDIR}/cloudflareddns_cf_zones + +networks: + traefik-net: + external: true + +services: + cloudflareddns: + image: ghcr.io/hotio/cloudflareddns + container_name: "${APPLICATION_NAME}" + networks: + - traefik-net + env_file: .cloudflareddns.env +# cloudflareddns doesn't support secrets +# secrets: +# - cloudflareddns_cf_user +# - cloudflareddns_cf_api_token +# - cloudflareddns_cf_hosts +# - cloudflareddns_cf_zones + volumes: + - ${DATADIR}/config:/config + restart: unless-stopped + + diff --git a/collabora/collabora_jm.txt b/collabora/collabora_jm.txt new file mode 100644 index 0000000..9dd415f --- /dev/null +++ b/collabora/collabora_jm.txt @@ -0,0 +1,60 @@ +# https://github.com/CollaboraOnline/online +# https://sdk.collaboraonline.com/docs/installation/CODE_Docker_image.html + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: collabor +Username: collabor +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +collabor UID: 3034 +collabor GID: 3033 + +Once off +-------- +# if not done already: +# add mapping for media: follow steps in "add mapping for media.txt" +# set ACL permissions for media in "set ACL permissions for media.txt" + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*collabora" +# create following datasets if not present +zfs create SSD1/docker/data/collabora +zfs create SSD1/docker/data/collabora/config +chown -R collabor:collabor /mnt/SSD1/docker/data/collabora + +Create folders +-------------- +mkdir -p /mnt/SSD1/docker/stacks/collabora/secrets + +Create secrets (collabora does not support docker secrets, so you can skip this section) +-------------- +cd /mnt/SSD1/docker/stacks/collabora/secrets +echo -n 'your_collabora_username' > /mnt/SSD1/docker/stacks/collabora/secrets/collabora_username +echo -n 'your_collabora_password' > /mnt/SSD1/docker/stacks/collabora/secrets/collabora_password +chown -R collabor:collabor /mnt/SSD1/docker/stacks/collabora/secrets +chmod -R 400 /mnt/SSD1/docker/stacks/collabora/secrets + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in collabora folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/collabora/ + +Admin console +------------- +https://collabora./browser/dist/admin/admin.html + + + diff --git a/collabora/coolwsd.xml b/collabora/coolwsd.xml new file mode 100644 index 0000000..212aa33 --- /dev/null +++ b/collabora/coolwsd.xml @@ -0,0 +1,350 @@ + + + + + + + + + + false + + + de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru + + + + + + + + + + + + + false + + + + + + + + + + + + + true + + + 4 + + + + 4 + 5 + 5 + false + 96 + 3600 + 30 + 300 + true + true + false + 0 + 8000 + 0 + 0 + 100 + 5 + 100 + 500 + 5000 + + 10000 + 60 + 300 + 3072 + 85 + 120 + + + + + 300 + 900 + + + + + + + true + + warning + trace + Socket,WebSocket,Admin,Pixel + notice + fatal + false + + -INFO-WARN + + + /var/log/coolwsd.log + never + timestamp + true + 10 days + 10 + true + false + + + false + 82589933 + + false + false + false + + + + + /var/log/coolwsd.trace.json + + + false + + + + + + + + false + + + + + + all + any + + + + 192\.168\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:192\.168\.[0-9]{1,3}\.[0-9]{1,3} + 127\.0\.0\.1 + ::ffff:127\.0\.0\.1 + ::1 + 172\.1[6789]\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:172\.1[6789]\.[0-9]{1,3}\.[0-9]{1,3} + 172\.2[0-9]\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:172\.2[0-9]\.[0-9]{1,3}\.[0-9]{1,3} + 172\.3[01]\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:172\.3[01]\.[0-9]{1,3}\.[0-9]{1,3} + 10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} + + + 192\.168\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:192\.168\.[0-9]{1,3}\.[0-9]{1,3} + 127\.0\.0\.1 + ::ffff:127\.0\.0\.1 + ::1 + 172\.1[6789]\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:172\.1[6789]\.[0-9]{1,3}\.[0-9]{1,3} + 172\.2[0-9]\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:172\.2[0-9]\.[0-9]{1,3}\.[0-9]{1,3} + 172\.3[01]\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:172\.3[01]\.[0-9]{1,3}\.[0-9]{1,3} + 10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} + ::ffff:10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} + localhost + + + + + + + + + + + + true + + false + /etc/coolwsd/cert.pem + /etc/coolwsd/key.pem + /etc/coolwsd/ca-chain.cert.pem + false + + + 1000 + + + + + + + false + 31536000 + + + + + true + + + true + + 1800 + false + 1 + false + false + + + + + + + + + + + + + + default + true + + + + + + 0 + + 900 + + + + + + + + + + + + true + + + + + + + + + + true + false + + + + true + true + true + true + + + + + + + + + + + + + + + + + + + false + + + + + + + false + + + + log + + + + + + + false + + + + + + + + + + + true + + + https://help.collaboraoffice.com/help.html? + + + true + + + + + + + + \ No newline at end of file diff --git a/collabora/stacks/.collabora.env b/collabora/stacks/.collabora.env new file mode 100644 index 0000000..6bad1ef --- /dev/null +++ b/collabora/stacks/.collabora.env @@ -0,0 +1,28 @@ +# https://www.collabora.org/docs/#env-configuration + +PUID=${PUID} +PGID=${MEDIA_GID} # we assign media gid to process gid to enable to access media folders +TZ=${TZ} +UMASK=0022 + +username=${USERNAME} +password=${PASSWORD} +#DONT_GEN_SSL_CERT=yes +cert_domain=${DOMAINNAME} +server_name=${APPLICATION_NAME}.${DOMAINNAME} +dictionaries="en_ZA en_US en_GB en_Afr" +# SSL terminates at the proxy +extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:user_interface.mode=compact --o:net.proto=IPv4 --o:hexify_embedded_urls=true --o:logging.level=warning #--o:welcome.enable=false + +#aliasgroup1=${NEXTCLOUD1} +#aliasgroup2=${NEXTCLOUD2} +#aliasgroup3=${NEXTCLOUD3} + +VIRTUAL_PROTO=http +VIRTUAL_PORT=9980 +VIRTUAL_HOST=${APPLICATION_NAME}.${DOMAINNAME} + +# letsencrypt_host=${APPLICATION_NAME}.${DOMAINNAME} + + + diff --git a/collabora/stacks/.env b/collabora/stacks/.env new file mode 100644 index 0000000..4a031b5 --- /dev/null +++ b/collabora/stacks/.env @@ -0,0 +1,29 @@ + +APPLICATION_NAME=collabora + +MEDIADIR=/mnt/stpool1/NData1/Media +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +CT_DOWNLOADS=/Downloads +CT_MEDIA=/Media +DOMAINNAME=sthome.org + +PUID=3034 +PGID=3033 +MEDIA_GID=3017 + +TZ=Africa/Johannesburg + +WEBUI_PORT=9980 + +# collabora does not support docker secrets +USERNAME=admin +PASSWORD="Saterdag!32#" + +NEXTCLOUD1= +NEXTCLOUD2= +NEXTCLOUD3= \ No newline at end of file diff --git a/collabora/stacks/compose.yml b/collabora/stacks/compose.yml new file mode 100644 index 0000000..80200fa --- /dev/null +++ b/collabora/stacks/compose.yml @@ -0,0 +1,69 @@ +# https://sdk.collaboraonline.com/docs/installation/CODE_Docker_image.html +# https://github.com/CollaboraOnline/online + +name: collabora + +secrets: + collabora_username: + file: ${SECRETSDIR}/collabora_username + collabora_password: + file: ${SECRETSDIR}/collabora_password + +networks: + traefik-net: + external: true + +services: + collabora: + image: collabora/code #:22.05.10.1.1 + hostname: collabora + env_file: .collabora.env + #user: "${PUID}:${PGID}" + tty: true + group_add: + - "${PGID}" + cap_add: + - MKNOD + networks: + - traefik-net + volumes: + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/config:/config" + restart: unless-stopped + secrets: + - collabora_username + - collabora_password + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http middlewares + # --------------------------- + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.permanent=true" + # + # http services + # ------------- + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http routers + # ------------ + # limit router to web ":80" entrypoint (Note: web entrypoint http requests are globally redirected to websecure router in traefik.yml) + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=${APPLICATION_NAME}-https-redirect" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # set router to be dedicated to secure requests only for the host specified in match criteria + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=sthomeresolver" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" diff --git a/cp2nas.ps1 b/cp2nas.ps1 new file mode 100644 index 0000000..b60c394 --- /dev/null +++ b/cp2nas.ps1 @@ -0,0 +1,135 @@ +############### CONST ############## +$destDockerDir="/mnt/SSD1/docker/" +$stacksfolder="stacks/" +$datafolder="data/" +$destStacks=$destDockerDir+$stacksfolder +$destData=$destDockerDir+$datafolder +$destTraefikRulesDir=$destStacks+"traefik/rules/" +$destTraefikUsersDir=$destStacks+"traefik/users/" +$destDataDir=$destData +############### MAIN ############### +# main function +# +$Main = +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + [Parameter(Mandatory=$false)] + [string[]] $apps + ) + $applist=[System.Collections.Generic.List[object]]::new() + If($PSBoundParameters.ContainsKey("apps")) { + foreach ($appname in $apps) + { + if ($appname.Contains('*')) { + $wclist=Get-ChildItem $appname -Directory | ForEach-Object { $_.Name } + # if wildcard is specified, we only add folders with a 'stacks' subfolder + foreach ($wcname in $wclist) { + if ((Test-Path -Path "$wcname\stacks")) { + $applist.Add($wcname) + } + } + } + else { + # here we don't have to check for a 'stacks' subfolder as the user specified appname explicitly + $applist.Add($appname) + } + } + # remove duplicates + $uniqlist=$applist | Sort-Object -Unique + foreach ($appname in $uniqlist) + { + copyfolder $destHost $appname "$appname\" + } + } + else { + # we're in the app subfolder, so only one stacks folder to copy + $appname="$pwd".Split("\\")[-1] + copyfolder $destHost $appname ".\" + } +} +####################################################################### +# copies specified folder to data folder on truenas +# +Function copytosubfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $folder, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $subfolder, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destdir + ) + $date=Get-Date -format "yyyy-MM-ddTHH:mm:ss" + if ((Test-Path -Path "$srcdir")) { + Write-Host "$date# pscp -P 22 -r ""$srcdir\*.*"" root@${destHost}:""${destdir}""" -ForegroundColor Green + Write-Host "Copying to ${destHost}:""${destDockerDir}" -NoNewline + Write-Host "${folder}" -ForegroundColor Cyan -NoNewline + Write-Host "${subfolder}" -ForegroundColor DarkYellow -NoNewline + Write-Host """:" + pscp -P 22 -r "$srcdir\*.*" root@${destHost}:""${destdir}"" + } +} +####################################################################### +# copies folder(s) to truenas +# +Function copyfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $subfolder, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir + ) + $srcStacksDir=$srcdir+"stacks" + $srcTraefikRulesDir=$srcdir+"traefik-rules" + $srcTraefikUsersDir=$srcdir+"traefik-users" + $srcDataDir=$srcdir+"data" + if (-Not(Test-Path -Path $srcStacksDir)) { + Write-Host "Source path doesn't exist: ""$PSScriptRoot\$srcStacksDir\*.*"". No files copied!" -ForegroundColor Red + Write-Host "Usage: in app folder : ./cp2nas DEST|IP" + Write-Host " in app parent folder: ./cp2nas DEST|IP app1, app2, app3, ..." + Write-Host " in app parent folder: ./cp2nas DEST|IP *" + Write-Host " in app parent folder: ./cp2nas DEST|IP wcstring1, wcstring2, ..." + return + } + $destAppStacksDir=$destStacks+$subfolder+"/" + # copy app folder destinations + copytosubfolder $destHost "${stacksfolder}" "${subfolder}" "${srcStacksDir}" "${destAppStacksDir}" + # copy traefik folder destinations + copytosubfolder $destHost "${stacksfolder}" "traefik/rules/" "${srcTraefikRulesDir}" "${destTraefikRulesDir}" + copytosubfolder $destHost "${stacksfolder}" "traefik/users/" "${srcTraefikUsersDir}" "${destTraefikUsersDir}" + # copy data folder destinations + copytosubfolder $destHost "${datafolder}" "${subfolder}/" "${srcDataDir}" "${destDataDir}${subfolder}" + +} + +################################### +# we call main proc from here +& $Main @Args \ No newline at end of file diff --git a/dashy/conf.txt b/dashy/conf.txt new file mode 100644 index 0000000..48c84f7 --- /dev/null +++ b/dashy/conf.txt @@ -0,0 +1,85 @@ +appConfig: + theme: lissy + layout: auto + iconSize: medium + language: en + startingView: default + defaultOpeningMethod: newtab + statusCheck: true + statusCheckInterval: 0 + faviconApi: allesedv + routingMode: history + enableMultiTasking: false + widgetsAlwaysUseProxy: false + webSearch: + disableWebSearch: false + searchEngine: google + openingMethod: newtab + searchBangs: {} + enableFontAwesome: true + enableMaterialDesignIcons: false + hideComponents: + hideHeading: false + hideNav: false + hideSearch: false + hideSettings: false + hideFooter: false + showSplashScreen: false + preventWriteToDisk: false + preventLocalSave: false + disableConfiguration: false + disableConfigurationForNonAdmin: false + allowConfigEdit: true + enableServiceWorker: false + disableContextMenu: false + disableUpdateChecks: false + disableSmartSort: false + enableErrorReporting: false +pageInfo: + title: Dashy + description: Welcome to your new dashboard! + navLinks: + - title: GitHub + path: https://github.com/Lissy93/dashy + target: newtab + - title: Documentation + path: https://dashy.to/docs + target: newtab + footerText: Dashy © 2023 +sections: + - name: Getting Started + icon: fas fa-rocket + items: [] + - name: Time + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: [] + - name: Docker Containers + icon: /icons/dashboard-icons/png/docker-moby.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Portainer + description: Docker container management + icon: >- + https://4731999.fs1.hubspotusercontent-na1.net/hubfs/4731999/crane-icon.svg + url: https://localhost:9443 + target: newtab + statusCheck: true + statusCheckUrl: https://localhost:9443 + id: 0_1678_portainer + - title: Dashy + icon: dashy + url: http://localhost:4000/ + target: newtab + statusCheck: true + statusCheckUrl: http://localhost:4000 + id: 1_1678_dashy diff --git a/dashy/dashboard.xlsx b/dashy/dashboard.xlsx new file mode 100644 index 0000000..6befaa0 Binary files /dev/null and b/dashy/dashboard.xlsx differ diff --git a/dashy/dashy_conf.yml b/dashy/dashy_conf.yml new file mode 100644 index 0000000..a0a5e41 --- /dev/null +++ b/dashy/dashy_conf.yml @@ -0,0 +1,617 @@ +appConfig: + theme: nord-frost + layout: auto + iconSize: large + language: en + statusCheck: true + statusCheckInterval: 20 +pageInfo: + title: sthome lab + description: Welcome to the sthome lab! + navLinks: + - title: GitHub + path: https://github.com/Lissy93/dashy + - title: DSERVER + path: https://dserver.sthome.lan + footerText: '' +sections: + - name: System Management + icon: fas fa-server + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_0 + title: Truenas + description: Truenas host + icon: dashboard-icons/svg/truenas.svg + url: https://truenas.sthome.org:444 + statusCheck: true + target: newtab + id: 0_1698_truenas + - &ref_1 + title: Dockge + description: Docker stack manager + icon: dashboard-icons/svg/dockge-light.svg + url: http://dockge.sthome.org:5001 + statusCheck: true + target: newtab + id: 1_1698_dockge + - &ref_2 + title: Proxmox + description: Proxmox host + icon: dashboard-icons/svg/proxmox.svg + url: http://10.0.0.22:8006/ + statusCheck: true + target: newtab + id: 2_1698_proxmox + - &ref_3 + title: Traefik + description: Reverse proxy and load balancer + icon: dashboard-icons/svg/traefik.svg + url: https://traefik.sthome.org + target: newtab + statusCheck: true + statusCheckUrl: http://traefik.sthome.org:8083/ping + id: 3_1698_traefik + filteredItems: + - *ref_0 + - *ref_1 + - *ref_2 + - *ref_3 + - name: Media Servers + icon: dashboard-icons/svg/media-playback.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_4 + title: Plex + description: Media server + icon: dashboard-icons/svg/plex.svg + url: https://plex.sthome.org + target: newtab + statusCheckUrl: https://plex.sthome.org/identity + id: 0_1258_plex + - &ref_5 + title: Jellyfin + description: Media server + icon: dashboard-icons/svg/jellyfin.svg + url: https://jellyfin.sthome.org + target: newtab + id: 1_1258_jellyfin + - &ref_6 + title: Emby + description: Media server + icon: dashboard-icons/svg/emby.svg + url: https://emby.sthome.org + target: newtab + id: 2_1258_emby + filteredItems: + - *ref_4 + - *ref_5 + - *ref_6 + - name: Books + icon: dashboard-icons/png/book.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_7 + title: Audiobookshelf + description: Audiobook and podcast server + icon: dashboard-icons/svg/audiobookshelf.svg + url: https://audiobookshelf.sthome.org + target: newtab + id: 0_510_audiobookshelf + - &ref_8 + title: Calibre + description: E-book manager + icon: dashboard-icons/svg/calibre.svg + url: https://calibre.sthome.org + target: newtab + id: 1_510_calibre + - &ref_9 + title: Kavita + description: Digital library + icon: dashboard-icons/svg/kavita.svg + url: https://kavita.sthome.org + target: newtab + id: 2_510_kavita + filteredItems: + - *ref_7 + - *ref_8 + - *ref_9 + - name: Home + icon: dashboard-icons/svg/home.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_10 + title: Home Assistant + description: Home automation + icon: dashboard-icons/svg/home-assistant.svg + url: https://home-assistant.sthome.org + target: newtab + id: 0_393_homeassistant + - &ref_11 + title: Frigate + description: Network Video Recorder + icon: dashboard-icons/svg/frigate.svg + url: https://frigate.sthome.org + target: newtab + statusCheck: true + statusCheckUrl: https://frigate.sthome.org/stats + id: 1_393_frigate + - &ref_12 + title: Mealie + description: Recipe manager + icon: dashboard-icons/svg/mealie.svg + url: https://mealie.sthome.org + target: newtab + id: 2_393_mealie + filteredItems: + - *ref_10 + - *ref_11 + - *ref_12 + - name: Security + icon: dashboard-icons/svg/security.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_13 + title: Authentik + description: Identity provider + icon: dashboard-icons/png/authentik.png + url: https://authentik.sthome.org + target: newtab + id: 0_856_authentik + - &ref_14 + title: Vaultwarden + description: Password manager + icon: dashboard-icons/svg/vaultwarden.svg + url: https://vaultwarden.sthome.org + target: newtab + id: 1_856_vaultwarden + filteredItems: + - *ref_13 + - *ref_14 + - name: Video Processing + icon: dashboard-icons/svg/video-camera.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_15 + title: Handbrake + description: Video Transcoder + icon: dashboard-icons/svg/handbrake.svg + url: https://handbrake.sthome.org + target: newtab + id: 0_1588_handbrake + - &ref_16 + title: MKVToolNix + description: MKV file editor and merger + icon: dashboard-icons/png/mkvtoolnix.png + url: https://mkvtoolnix.sthome.org + target: newtab + id: 1_1588_mkvtoolnix + filteredItems: + - *ref_15 + - *ref_16 + - name: Photos + icon: dashboard-icons/svg/photos.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_17 + title: Digikam + description: Image organizer and tag editor + icon: dashboard-icons/svg/digikam_oxygen.svg + url: https://digikam.sthome.org + target: newtab + id: 0_637_digikam + - &ref_18 + title: Photoview + description: Photo gallery + icon: dashboard-icons/svg/photoview.svg + url: https://photoview.sthome.org + target: newtab + id: 1_637_photoview + filteredItems: + - *ref_17 + - *ref_18 + - name: Finance + icon: dashboard-icons/svg/financial-services.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_19 + title: Firefly III + description: Personal finance manager + icon: dashboard-icons/png/firefly.png + url: https://firefly.sthome.org + target: newtab + statusCheck: true + statusCheckHeaders: https://firefly.sthome.org/health + id: 0_692_fireflyiii + filteredItems: + - *ref_19 + - name: Development + icon: dashboard-icons/png/software-development.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_20 + title: Gitea + description: >- + Software development service; Git hosting, code review, team + collaboration, package registry and CI/CD + icon: dashboard-icons/svg/gitea.svg + url: https://gitea.sthome.org + target: newtab + id: 0_1155_gitea + filteredItems: + - *ref_20 + - name: Performance + icon: dashboard-icons/png/data-analysis.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_21 + title: Grafana + description: Analytics & monitoring + icon: dashboard-icons/svg/grafana.svg + url: https://grafana.sthome.org + target: newtab + id: 0_1138_grafana + - &ref_22 + title: Prometheus + description: Event monitoring and alerting + icon: dashboard-icons/svg/prometheus.svg + url: https://prometheus.sthome.org + target: newtab + statusCheck: true + statusCheckUrl: https://prometheus.sthome.org/-/healthy + id: 1_1138_prometheus + filteredItems: + - *ref_21 + - *ref_22 + - name: Network + icon: dashboard-icons/svg/network.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_23 + title: Librespeed + description: Network speed tester + icon: dashboard-icons/svg/librespeed.svg + url: https://librespeed.sthome.org + target: newtab + id: 0_746_librespeed + - &ref_24 + title: Pi-hole + description: DNS sinkhole + icon: dashboard-icons/svg/pi-hole.svg + url: https://pihole.sthome.org/admin + target: newtab + statusCheckUrl: http://pihole.sthome.org/admin/api.php?status + id: 1_746_pihole + filteredItems: + - *ref_23 + - *ref_24 + - name: Web Site + icon: dashboard-icons/svg/web-server.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_25 + title: Static-Web-Server + description: Web server + icon: dashboard-icons/png/static-web-server.png + url: https://www.sthome.org + target: newtab + id: 0_723_staticwebserver + filteredItems: + - *ref_25 + - name: Music + icon: dashboard-icons/svg/music.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_26 + title: Sheetable + description: Music sheet organiser + icon: dashboard-icons/png/sheetable.png + url: https://sheetable.sthome.org + target: newtab + id: 0_513_sheetable + - &ref_27 + title: Songkong + description: Music tagger + icon: dashboard-icons/png/songkong.png + url: https://songkong.sthome.org + target: newtab + id: 1_513_songkong + filteredItems: + - *ref_26 + - *ref_27 + - name: Collaboration + icon: dashboard-icons/png/collaboration.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_28 + title: Nextcloud + description: Content collaboration platform + icon: dashboard-icons/svg/nextcloud.svg + url: https://nextcloud.sthome.org + target: newtab + id: 0_1353_nextcloud + - &ref_29 + title: Onlyoffice + description: Secure online office suite + icon: dashboard-icons/svg/onlyoffice.svg + url: https://onlyoffice.sthome.org + target: newtab + id: 1_1353_onlyoffice + filteredItems: + - *ref_28 + - *ref_29 + - name: Data Analysis + icon: dashboard-icons/png/data-analysis.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_30 + title: Root + description: Data analysis framework + icon: dashboard-icons/png/root.png + url: https://root.sthome.org + target: newtab + id: 0_1246_root + filteredItems: + - *ref_30 + - name: Gaming + icon: dashboard-icons/svg/gaming.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - &ref_31 + title: Minecraft Bedrock + description: >- + Use https://mc-bedrock.sthome.org to setup minecraft server url in + game + icon: dashboard-icons/svg/minecraft.svg + url: https://mc-bedrock.sthome.org + target: newtab + id: 0_595_minecraftbedrock + - &ref_32 + title: Minecraft Java + description: Use https://mc-java.sthome.org to setup minecraft server url in game + icon: dashboard-icons/svg/minecraft.svg + url: https://mc-java.sthome.org + target: newtab + id: 1_595_minecraftjava + filteredItems: + - *ref_31 + - *ref_32 + - name: Media Management + icon: dashboard-icons/svg/media.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: true + hideForGuests: false + items: + - &ref_33 + title: Lidarr + description: Music collection manager + icon: dashboard-icons/svg/lidarr.svg + url: https://lidarr.sthome.org + target: newtab + id: 0_1533_lidarr + - &ref_34 + title: Mediaelch + description: Media manager for Kodi + icon: dashboard-icons/png/mediaelch.png + url: https://mediaelch.sthome.org + target: newtab + id: 1_1533_mediaelch + - &ref_35 + title: Overseerr + description: Request management and media discovery + icon: dashboard-icons/svg/overseerr.svg + url: https://overseerr.sthome.org + target: newtab + id: 2_1533_overseerr + - &ref_36 + title: Prowlarr + description: Indexer manager/proxy + icon: dashboard-icons/svg/prowlarr.svg + url: https://prowlarr.sthome.org + target: newtab + id: 3_1533_prowlarr + - &ref_37 + title: qBittorrent + description: P2P bittorrent client + icon: dashboard-icons/svg/qbittorrent.svg + url: https://qbittorrent.sthome.org + target: newtab + id: 4_1533_qbittorrent + - &ref_38 + title: Radarr + description: Movie collection manager + icon: dashboard-icons/svg/radarr.svg + url: https://radarr.sthome.org + target: newtab + id: 5_1533_radarr + - &ref_39 + title: Readarr + description: "\_ebook collection manage" + icon: dashboard-icons/svg/readarr.svg + url: https://readarr.sthome.org + target: newtab + id: 6_1533_readarr + - &ref_40 + title: Sonarr + description: Internet PVR for Usenet and Torrents + icon: dashboard-icons/svg/sonarr.svg + url: https://sonarr.sthome.org + target: newtab + id: 7_1533_sonarr + - &ref_41 + title: Tautulli + description: Monitoring, analytics and notifications for Plex + icon: dashboard-icons/svg/tautulli.svg + url: https://tautulli.sthome.org + target: newtab + id: 8_1533_tautulli + filteredItems: + - *ref_33 + - *ref_34 + - *ref_35 + - *ref_36 + - *ref_37 + - *ref_38 + - *ref_39 + - *ref_40 + - *ref_41 + - name: VPN + icon: dashboard-icons/svg/shield-user.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: true + hideForGuests: false + items: + - &ref_42 + title: WG-easy + description: VPN server + icon: dashboard-icons/svg/wireguard.svg + url: https://vpn.sthome.org + target: newtab + id: 0_244_wgeasy + - &ref_43 + title: jDownloader2 + description: Download manager + icon: dashboard-icons/png/jdownloader2.png + url: https://jdownloader2.sthome.org + target: newtab + id: 1_244_jdownloader + - &ref_44 + title: Firefox + description: Browser + icon: dashboard-icons/svg/firefox.svg + url: https://firefox.sthome.org + target: newtab + id: 2_244_firefox + filteredItems: + - *ref_42 + - *ref_43 + - *ref_44 + - name: Data Management + icon: dashboard-icons/svg/database.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: true + hideForGuests: false + items: + - &ref_45 + title: Minio + description: Object Storage - S3 compatible + icon: dashboard-icons/svg/minio.svg + url: https://minio1.sthome.org + target: newtab + id: 0_1431_minio + - &ref_46 + title: Minio + description: Object Storage - S3 compatible + icon: dashboard-icons/svg/minio.svg + url: https://minio2.sthome.org + target: newtab + id: 1_1431_minio + - &ref_47 + title: pgAdmin + description: Administration and development platform for PostgreSQL + icon: dashboard-icons/svg/pgadmin.svg + url: https://pgadmin.sthome.org + target: newtab + statusCheckUrl: 'https://pgadmin.sthome.org/misc/ping ' + id: 2_1431_pgadmin + - &ref_48 + title: Syncthing + description: Continuous file synchronization program + icon: dashboard-icons/svg/syncthing.svg + url: https://syncthing.sthome.org + target: newtab + id: 3_1431_syncthing + filteredItems: + - *ref_45 + - *ref_46 + - *ref_47 + - *ref_48 diff --git a/dashy/data/appdata/icons/dashboard-icons/png/book.png b/dashy/data/appdata/icons/dashboard-icons/png/book.png new file mode 100644 index 0000000..582fcb1 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/book.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/collaboration.png b/dashy/data/appdata/icons/dashboard-icons/png/collaboration.png new file mode 100644 index 0000000..aae7cd7 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/collaboration.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/data-analysis.png b/dashy/data/appdata/icons/dashboard-icons/png/data-analysis.png new file mode 100644 index 0000000..614cf0a Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/data-analysis.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/file-transfer.jpg b/dashy/data/appdata/icons/dashboard-icons/png/file-transfer.jpg new file mode 100644 index 0000000..42a9722 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/file-transfer.jpg differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/file-transfer.png b/dashy/data/appdata/icons/dashboard-icons/png/file-transfer.png new file mode 100644 index 0000000..608c733 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/file-transfer.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/mediaelch.png b/dashy/data/appdata/icons/dashboard-icons/png/mediaelch.png new file mode 100644 index 0000000..f807743 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/mediaelch.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/root.png b/dashy/data/appdata/icons/dashboard-icons/png/root.png new file mode 100644 index 0000000..3d4a1cb Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/root.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/sftpgo.png b/dashy/data/appdata/icons/dashboard-icons/png/sftpgo.png new file mode 100644 index 0000000..19500d1 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/sftpgo.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/sheetable.png b/dashy/data/appdata/icons/dashboard-icons/png/sheetable.png new file mode 100644 index 0000000..d17d177 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/sheetable.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/software-development.png b/dashy/data/appdata/icons/dashboard-icons/png/software-development.png new file mode 100644 index 0000000..f44be46 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/software-development.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/songkong.png b/dashy/data/appdata/icons/dashboard-icons/png/songkong.png new file mode 100644 index 0000000..fecd58d Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/songkong.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/png/static-web-server.png b/dashy/data/appdata/icons/dashboard-icons/png/static-web-server.png new file mode 100644 index 0000000..0daeb08 Binary files /dev/null and b/dashy/data/appdata/icons/dashboard-icons/png/static-web-server.png differ diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/database.svg b/dashy/data/appdata/icons/dashboard-icons/svg/database.svg new file mode 100644 index 0000000..a37eef6 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/database.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/digikam.svg b/dashy/data/appdata/icons/dashboard-icons/svg/digikam.svg new file mode 100644 index 0000000..d0db7eb --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/digikam.svg @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/digikam_oxygen.svg b/dashy/data/appdata/icons/dashboard-icons/svg/digikam_oxygen.svg new file mode 100644 index 0000000..bbf63d5 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/digikam_oxygen.svg @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/financial-services.svg b/dashy/data/appdata/icons/dashboard-icons/svg/financial-services.svg new file mode 100644 index 0000000..0d20d8a --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/financial-services.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/gaming.svg b/dashy/data/appdata/icons/dashboard-icons/svg/gaming.svg new file mode 100644 index 0000000..c792bc3 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/gaming.svg @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/home.svg b/dashy/data/appdata/icons/dashboard-icons/svg/home.svg new file mode 100644 index 0000000..09ebbb3 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/home.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/home2.svg b/dashy/data/appdata/icons/dashboard-icons/svg/home2.svg new file mode 100644 index 0000000..45379a7 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/home2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/media-playback.svg b/dashy/data/appdata/icons/dashboard-icons/svg/media-playback.svg new file mode 100644 index 0000000..0e8473e --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/media-playback.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/media.svg b/dashy/data/appdata/icons/dashboard-icons/svg/media.svg new file mode 100644 index 0000000..20dcd1c --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/media.svg @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/music.svg b/dashy/data/appdata/icons/dashboard-icons/svg/music.svg new file mode 100644 index 0000000..6617c47 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/music.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/network.svg b/dashy/data/appdata/icons/dashboard-icons/svg/network.svg new file mode 100644 index 0000000..ba7b330 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/network.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/photos.svg b/dashy/data/appdata/icons/dashboard-icons/svg/photos.svg new file mode 100644 index 0000000..58a8799 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/photos.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/security.svg b/dashy/data/appdata/icons/dashboard-icons/svg/security.svg new file mode 100644 index 0000000..c803155 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/security.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/shield-user.svg b/dashy/data/appdata/icons/dashboard-icons/svg/shield-user.svg new file mode 100644 index 0000000..82fa67d --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/shield-user.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/traffic-cone.svg b/dashy/data/appdata/icons/dashboard-icons/svg/traffic-cone.svg new file mode 100644 index 0000000..d04ea31 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/traffic-cone.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/video-camera.svg b/dashy/data/appdata/icons/dashboard-icons/svg/video-camera.svg new file mode 100644 index 0000000..e7b8f45 --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/video-camera.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dashy/data/appdata/icons/dashboard-icons/svg/web-server.svg b/dashy/data/appdata/icons/dashboard-icons/svg/web-server.svg new file mode 100644 index 0000000..2636aea --- /dev/null +++ b/dashy/data/appdata/icons/dashboard-icons/svg/web-server.svg @@ -0,0 +1 @@ +web-server \ No newline at end of file diff --git a/dashy/data/config/config.yml b/dashy/data/config/config.yml new file mode 100644 index 0000000..c90d34a --- /dev/null +++ b/dashy/data/config/config.yml @@ -0,0 +1,551 @@ +pages: + - name: Widgets + path: 'widgets.yml' +appConfig: + theme: one-dark + layout: auto + iconSize: large + language: en + statusCheck: true + statusCheckInterval: 20 +pageInfo: + title: sthome lab + description: Welcome to the sthome lab! + navLinks: + - title: Google + path: https://google.co.za +# - title: GitHub +# path: https://github.com/Lissy93/dashy +# - title: DSERVER +# path: https://dserver.sthome.lan + - title: "Phone GUI" + path: https://w60b.sthome.org + - title: "Router" + path: https://10.0.0.2 + - title: "FANART" + path: https://fanart.tv/ + - title: "MusicBrainz" + path: https://musicbrainz.org/ +# - title: "TheAudioDB" +# path: https://www.theaudiodb.com/ + - title: "Cloudflare" + path: https://dash.cloudflare.com/login + footerText: '' +sections: + - name: System Management + icon: fas fa-server + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Truenas + description: Truenas host + icon: dashboard-icons/svg/truenas.svg + url: https://truenas.sthome.org:444 + statusCheck: true + statusCheckUrl: https://truenas.sthome.org:444 + target: newtab + - title: Dockge + description: Docker stack manager + icon: dashboard-icons/svg/dockge-light.svg + url: http://dockge.sthome.org:5001 + statusCheck: true + target: newtab + - title: Proxmox + description: Proxmox host + icon: dashboard-icons/svg/proxmox.svg + url: https://pve.sthome.org:8006 + statusCheck: true + statusCheckUrl: https://pve.sthome.org:8006 + target: newtab + - title: Traefik + description: Reverse proxy and load balancer + icon: dashboard-icons/svg/traefik.svg + url: https://traefik.sthome.org + statusCheck: true + statusCheckUrl: http://traefik.sthome.org:8083/ping + target: newtab + - name: Media Servers + icon: dashboard-icons/svg/media-playback.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Plex + description: Media server + icon: dashboard-icons/svg/plex.svg + url: https://plex.sthome.org + statusCheck: true + statusCheckUrl: https://plex.sthome.org/identity + target: newtab + tags: [ movies, videos, music ] + - title: Jellyfin + description: Media server + icon: dashboard-icons/svg/jellyfin.svg + url: https://jellyfin.sthome.org + target: newtab + - title: Emby + description: Media server + icon: dashboard-icons/svg/emby.svg + url: https://emby.sthome.org + target: newtab + - name: Books + icon: dashboard-icons/png/book.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Audiobookshelf + description: Audiobook and podcast server + icon: dashboard-icons/svg/audiobookshelf.svg + url: https://audiobookshelf.sthome.org + target: newtab + - title: Calibre + description: E-book manager + icon: dashboard-icons/svg/calibre.svg + url: https://calibre.sthome.org + target: newtab + - title: Kavita + description: Digital library + icon: dashboard-icons/svg/kavita.svg + url: https://kavita.sthome.org + target: newtab + - name: Home + icon: dashboard-icons/svg/home.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Home Assistant + description: Home automation + icon: dashboard-icons/svg/home-assistant.svg + url: https://home-assistant.sthome.org + target: newtab + - title: Frigate + description: Network video recorder + icon: dashboard-icons/svg/frigate.svg + url: https://frigate.sthome.org + statusCheck: true + statusCheckUrl: https://frigate.sthome.org/stats + target: newtab + - title: Mealie + description: Recipe manager + icon: dashboard-icons/svg/mealie.svg + url: https://mealie.sthome.org + target: newtab +# + - name: Security + icon: dashboard-icons/svg/security.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Authentik + description: Identity provider + icon: dashboard-icons/png/authentik.png + url: http://authentik.sthome.org + target: newtab + - title: Vaultwarden + description: Password manager + icon: dashboard-icons/svg/vaultwarden.svg + url: https://vaultwarden.sthome.org + target: newtab + - name: Video Processing + icon: dashboard-icons/svg/video-camera.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Handbrake + description: Video Transcoder + icon: dashboard-icons/svg/handbrake.svg + url: https://handbrake.sthome.org + target: newtab + - title: MKVToolNix + description: MKV file editor and merger + icon: dashboard-icons/png/mkvtoolnix.png + url: https://mkvtoolnix.sthome.org + target: newtab + - name: Photos + icon: dashboard-icons/svg/photos.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Digikam + description: Image organizer and tag editor + icon: dashboard-icons/svg/digikam_oxygen.svg + url: https://digikam.sthome.org + target: newtab + - title: Photoview + description: Photo gallery + icon: dashboard-icons/svg/photoview.svg + url: https://photoview.sthome.org + target: newtab + + - name: Finance + icon: dashboard-icons/svg/financial-services.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Firefly III + description: Personal finance manager + icon: dashboard-icons/png/firefly.png + url: https://firefly.sthome.org + statusCheck: true + statusCheckUrl: https://firefly.sthome.org/health + target: newtab +# + - name: Development + icon: dashboard-icons/png/software-development.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Gitea + description: Software development service; Git hosting, code review, team collaboration, package registry and CI/CD + icon: dashboard-icons/svg/gitea.svg + url: https://gitea.sthome.org + target: newtab + - name: Performance + icon: dashboard-icons/png/data-analysis.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Grafana + description: Analytics & monitoring + icon: dashboard-icons/svg/grafana.svg + url: https://grafana.sthome.org + target: newtab + - title: Prometheus + description: Event monitoring and alerting + icon: dashboard-icons/svg/prometheus.svg + url: https://prometheus.sthome.org + statusCheck: true + statusCheckUrl: https://prometheus.sthome.org/-/healthy + target: newtab + - name: Network + icon: dashboard-icons/svg/network.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Librespeed + description: Network speed tester + icon: dashboard-icons/svg/librespeed.svg + url: https://librespeed.sthome.org + target: newtab + - title: Pi-hole + description: DNS sinkhole + icon: dashboard-icons/svg/pi-hole.svg + url: https://pihole.sthome.org/admin + statusCheck: true + statusCheckUrl: https://pihole.sthome.org/admin/api.php?status + target: newtab + - name: Web Site + icon: dashboard-icons/svg/web-server.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Static-Web-Server + description: Web server + icon: dashboard-icons/png/static-web-server.png + url: https://www.sthome.org + target: newtab + - title: Uptime-kuma + description: Uptime monitoring + icon: dashboard-icons/svg/uptime-kuma.svg + url: https://uptime-kuma.sthome.org + statusCheck: true + statusCheckUrl: https://uptime-kuma.sthome.org + target: newtab + + - name: Music + icon: dashboard-icons/svg/music.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Sheetable + description: Music sheet organiser + icon: dashboard-icons/png/sheetable.png + url: https://sheetable.sthome.org + target: newtab + - title: Songkong + description: Music tagger + icon: dashboard-icons/png/songkong.png + url: https://songkong.sthome.org + target: newtab + + - name: Collaboration + icon: dashboard-icons/png/collaboration.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Nextcloud + description: Content collaboration platform + icon: dashboard-icons/svg/nextcloud.svg + url: https://nextcloud.sthome.org + target: newtab + - title: Onlyoffice + description: Secure online office suite + icon: dashboard-icons/svg/onlyoffice.svg + url: https://onlyoffice.sthome.org + target: newtab + - name: Data Analysis + icon: dashboard-icons/png/data-analysis.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Root + description: Data analysis framework + icon: dashboard-icons/png/root.png + url: https://root.sthome.org + target: newtab +# - name: Gaming +# icon: dashboard-icons/svg/gaming.svg +# displayData: +# sortBy: default +# rows: 1 +# cols: 1 +# collapsed: false +# hideForGuests: false +# items: +# - title: Minecraft Bedrock +# description: Use port 19132 +# icon: dashboard-icons/svg/minecraft.svg +# url: https://minecraft.sthome.org +# statusCheck: true +# statusCheckUrl: udp://minecraft.sthome.org:19132 +# target: newtab +# - title: Minecraft Java +# description: Use port 25565 +# icon: dashboard-icons/svg/minecraft.svg +# url: https://minecraft.sthome.org +# statusCheck: true +# statusCheckUrl: udp://minecraft.sthome.org:25565 +# target: newtab + - name: File Transfer + icon: dashboard-icons/png/file-transfer.png + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: SFTPGo + description: SFTP, FTP/S, HTTP/S and WebDAV server + icon: dashboard-icons/png/sftpgo.png + url: https://sftpgo.sthome.org/web/admin/login + statusCheck: true + statusCheckUrl: https://sftpgo.sthome.org + target: newtab + +# + - name: Media Management + icon: dashboard-icons/svg/media.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Lidarr + description: Music collection manager + icon: dashboard-icons/svg/lidarr.svg + url: https://lidarr.sthome.org + target: newtab + - title: Mediaelch + description: Media manager for Kodi + icon: dashboard-icons/png/mediaelch.png + url: https://mediaelch.sthome.org + target: newtab + - title: Overseerr + description: Request management and media discovery + icon: dashboard-icons/svg/overseerr.svg + url: https://overseerr.sthome.org + target: newtab + - title: Prowlarr + description: Indexer manager/proxy + icon: dashboard-icons/svg/prowlarr.svg + url: https://prowlarr.sthome.org + target: newtab + - title: qBittorrent + description: P2P bittorrent client + icon: dashboard-icons/svg/qbittorrent.svg + url: https://qbittorrent.sthome.org + target: newtab + - title: Radarr + description: Movie collection manager + icon: dashboard-icons/svg/radarr.svg + url: https://radarr.sthome.org + target: newtab + - title: Readarr + description:  ebook collection manage + icon: dashboard-icons/svg/readarr.svg + url: https://readarr.sthome.org + target: newtab + - title: Sonarr + description: Internet PVR for Usenet and Torrents + icon: dashboard-icons/svg/sonarr.svg + url: https://sonarr.sthome.org + target: newtab + - title: Tautulli + description: Monitoring, analytics and notifications for Plex + icon: dashboard-icons/svg/tautulli.svg + url: https://tautulli.sthome.org + target: newtab + widgets: + - type: public-holidays + options: + country: ZA + region: ZA-GP + holidayType: all + monthsToShow: 12 + lang: en + - name: VPN + icon: dashboard-icons/svg/shield-user.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: WG-easy + description: VPN server + icon: dashboard-icons/svg/wireguard.svg + url: https://vpn.sthome.org + target: newtab + - title: jDownloader2 + description: Download manager + icon: dashboard-icons/png/jdownloader2.png + url: https://jdownloader2.sthome.org + target: newtab + - title: Firefox + description: Browser + icon: dashboard-icons/svg/firefox.svg + url: https://firefox.sthome.org + target: newtab + widgets: + - type: gluetun-status + useProxy: true + options: + hostname: https://gluetun-arr:8000 + #visibleFields: public_ip,region,country,city,location,organisation,postal_code,timezone + visibleFields: public_ip,city,region,country + - type: gluetun-status + useProxy: true + options: + hostname: https://gluetun-bw:8000 + visibleFields: public_ip,city,region,country + - type: public-ip + options: + provider: ipgeolocation + apiKey: 1760272ad3194398a0f9715323a12a90 + - name: Data Management + icon: dashboard-icons/svg/database.svg + displayData: + sortBy: default + rows: 1 + cols: 1 + collapsed: false + hideForGuests: false + items: + - title: Minio + description: Object Storage - S3 compatible + icon: dashboard-icons/svg/minio.svg + url: https://minio1.sthome.org + target: newtab + - title: Minio + description: Object Storage - S3 compatible + icon: dashboard-icons/svg/minio.svg + url: https://minio2.sthome.org + target: newtab + - title: pgAdmin + description: Administration and development platform for PostgreSQL + icon: dashboard-icons/svg/pgadmin.svg + url: https://pgadmin.sthome.org + statusCheck: true + statusCheckUrl: https://pgadmin.sthome.org/misc/ping + target: newtab + - title: Syncthing + description: Continuous file synchronization program + icon: dashboard-icons/svg/syncthing.svg + url: https://syncthing.sthome.org + target: newtab + widgets: + - type: clock + options: + timeZone: Africa/Johannesburg + format: en-ZA + customCityName: Pretoria + hideDate: false + hideSeconds: false + - type: domain-monitor + options: + domain: sthome.org + apiKey: bdbab262b92d2f6857852973343aa62c + - type: domain-monitor + options: + domain: stokvis.co.za + apiKey: bdbab262b92d2f6857852973343aa62c +# + - name: News + widgets: + - type: news-headlines + options: + apiKey: MQts_PB-VrTD7a-xjNQ6EBxeoJIcKRLlsyPdmKT8yWrJcMZT + category: world \ No newline at end of file diff --git a/dashy/data/config/widgets.yml b/dashy/data/config/widgets.yml new file mode 100644 index 0000000..6dee06d --- /dev/null +++ b/dashy/data/config/widgets.yml @@ -0,0 +1,116 @@ +#appConfig: +# theme: one-dark +# layout: auto +# iconSize: large +# language: en +# statusCheck: true +# statusCheckInterval: 20 +pageInfo: + title: sthome lab + footerText: '' +sections: + - name: Picture of the day + widgets: + - type: apod + - name: Info + widgets: + - type: crypto-watch-list + options: + currency: ZAR + sortBy: marketCap + assets: + - bitcoin + - ethereum + - type: crypto-price-chart + options: + asset: bitcoin + currency: ZAR + numDays: 7 + - type: exchange-rates + options: + apiKey: 275e8fe7e74067617a0eb2be + inputCurrency: USD + outputCurrencies: + - ZAR + + - type: exchange-rates + options: + apiKey: 275e8fe7e74067617a0eb2be + inputCurrency: GBP + outputCurrencies: + - ZAR + - USD + + - name: Misc + widgets: + - type: joke + options: + safeMode: true + language: en + category: Any + - type: xkcd-comic + options: + comic: latest + + - type: github-profile-stats + options: + username: stuurmcp + hideLanguagesCard: true + #repos: + #- stuurmcp/cert-manager-webhook-sthome + + +# - type: cve-vulnerabilities +# options: +# sortBy: publish-date +# vendorId: 26 +# hasExploit: false +# minScore: 5 +# limit: 30 +# - type: sports-scores +# options: +# teamId: 133636 +# - type: cve-vulnerabilities +# options: +# sortBy: publish-date +# productId: 28125 +# hasExploit: false +# minScore: 5 +# limit: 30 +# - type: stock-price-chart +# options: +# stock: TKG +# apiKey: N3WSQJ9OODXXYFT6 +# - type: github-trending-repos +# options: +# limit: 8 +# since: weekly +# - type: pi-hole-stats +# options: +# hostname: http://pihole.sthome.org/admin/api.php?status +# apiKey: 48ab5845603098040b5d2455c2600cf14b643424f508d5aa30bb884ac11f55c3 +# - type: pi-hole-top-queries +# options: +# hostname: http://pihole.sthome.org +# apiKey: 48ab5845603098040b5d2455c2600cf14b643424f508d5aa30bb884ac11f55c3 +# - type: proxmox-lists +# useProxy: true +# options: +# cluster_url: http://10.0.0.22:8006 +# user_name: root@pam +# token_name: dashy +# token_uuid: e94ec098-8367-44d9-8818-49f20a56801d +## node: proxmox +## node_data: qemu +## title: Proxmox VMs +## title_as_link: false +## footer: Proxmox +## footer_as_link: true +## hide_templates: 1 + +# - name: News +# widgets: +# - type: news-headlines +# options: +# apiKey: MQts_PB-VrTD7a-xjNQ6EBxeoJIcKRLlsyPdmKT8yWrJcMZT +# category: world diff --git a/dashy/icons-temp/book-black.png b/dashy/icons-temp/book-black.png new file mode 100644 index 0000000..582fcb1 Binary files /dev/null and b/dashy/icons-temp/book-black.png differ diff --git a/dashy/icons-temp/book-black.psd b/dashy/icons-temp/book-black.psd new file mode 100644 index 0000000..b2ea57c Binary files /dev/null and b/dashy/icons-temp/book-black.psd differ diff --git a/dashy/icons-temp/book-white.png b/dashy/icons-temp/book-white.png new file mode 100644 index 0000000..ca19a53 Binary files /dev/null and b/dashy/icons-temp/book-white.png differ diff --git a/dashy/icons-temp/book-white.psd b/dashy/icons-temp/book-white.psd new file mode 100644 index 0000000..84fd987 Binary files /dev/null and b/dashy/icons-temp/book-white.psd differ diff --git a/dashy/icons-temp/book.psd b/dashy/icons-temp/book.psd new file mode 100644 index 0000000..fb7e596 Binary files /dev/null and b/dashy/icons-temp/book.psd differ diff --git a/dashy/icons-temp/collaboration.png b/dashy/icons-temp/collaboration.png new file mode 100644 index 0000000..aae7cd7 Binary files /dev/null and b/dashy/icons-temp/collaboration.png differ diff --git a/dashy/icons-temp/collaboration.psd b/dashy/icons-temp/collaboration.psd new file mode 100644 index 0000000..3404da6 Binary files /dev/null and b/dashy/icons-temp/collaboration.psd differ diff --git a/dashy/icons-temp/data-analysis.png b/dashy/icons-temp/data-analysis.png new file mode 100644 index 0000000..614cf0a Binary files /dev/null and b/dashy/icons-temp/data-analysis.png differ diff --git a/dashy/icons-temp/data-analysis.psd b/dashy/icons-temp/data-analysis.psd new file mode 100644 index 0000000..dab37eb Binary files /dev/null and b/dashy/icons-temp/data-analysis.psd differ diff --git a/dashy/icons-temp/data-update.svg b/dashy/icons-temp/data-update.svg new file mode 100644 index 0000000..6757737 --- /dev/null +++ b/dashy/icons-temp/data-update.svg @@ -0,0 +1 @@ +data-update \ No newline at end of file diff --git a/dashy/icons-temp/database.svg b/dashy/icons-temp/database.svg new file mode 100644 index 0000000..a37eef6 --- /dev/null +++ b/dashy/icons-temp/database.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dashy/icons-temp/digikam.svg b/dashy/icons-temp/digikam.svg new file mode 100644 index 0000000..d0db7eb --- /dev/null +++ b/dashy/icons-temp/digikam.svg @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashy/icons-temp/digikam_oxygen.svg b/dashy/icons-temp/digikam_oxygen.svg new file mode 100644 index 0000000..bbf63d5 --- /dev/null +++ b/dashy/icons-temp/digikam_oxygen.svg @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashy/icons-temp/financial-services.svg b/dashy/icons-temp/financial-services.svg new file mode 100644 index 0000000..0d20d8a --- /dev/null +++ b/dashy/icons-temp/financial-services.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/dashy/icons-temp/gaming.svg b/dashy/icons-temp/gaming.svg new file mode 100644 index 0000000..c792bc3 --- /dev/null +++ b/dashy/icons-temp/gaming.svg @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/dashy/icons-temp/generic-logo-black-512.png b/dashy/icons-temp/generic-logo-black-512.png new file mode 100644 index 0000000..c2ed827 Binary files /dev/null and b/dashy/icons-temp/generic-logo-black-512.png differ diff --git a/dashy/icons-temp/generic-logo-color-shadowed-512.png b/dashy/icons-temp/generic-logo-color-shadowed-512.png new file mode 100644 index 0000000..aa87382 Binary files /dev/null and b/dashy/icons-temp/generic-logo-color-shadowed-512.png differ diff --git a/dashy/icons-temp/generic-logo-cyan-512.png b/dashy/icons-temp/generic-logo-cyan-512.png new file mode 100644 index 0000000..8da1bbf Binary files /dev/null and b/dashy/icons-temp/generic-logo-cyan-512.png differ diff --git a/dashy/icons-temp/home.svg b/dashy/icons-temp/home.svg new file mode 100644 index 0000000..45379a7 --- /dev/null +++ b/dashy/icons-temp/home.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/icons-temp/media-playback.svg b/dashy/icons-temp/media-playback.svg new file mode 100644 index 0000000..0e8473e --- /dev/null +++ b/dashy/icons-temp/media-playback.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dashy/icons-temp/media.svg b/dashy/icons-temp/media.svg new file mode 100644 index 0000000..20dcd1c --- /dev/null +++ b/dashy/icons-temp/media.svg @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/dashy/icons-temp/mediaelch.png b/dashy/icons-temp/mediaelch.png new file mode 100644 index 0000000..f807743 Binary files /dev/null and b/dashy/icons-temp/mediaelch.png differ diff --git a/dashy/icons-temp/music.svg b/dashy/icons-temp/music.svg new file mode 100644 index 0000000..6617c47 --- /dev/null +++ b/dashy/icons-temp/music.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/icons-temp/network.svg b/dashy/icons-temp/network.svg new file mode 100644 index 0000000..ba7b330 --- /dev/null +++ b/dashy/icons-temp/network.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/icons-temp/photos.svg b/dashy/icons-temp/photos.svg new file mode 100644 index 0000000..58a8799 --- /dev/null +++ b/dashy/icons-temp/photos.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dashy/icons-temp/policeman.svg b/dashy/icons-temp/policeman.svg new file mode 100644 index 0000000..87419ab --- /dev/null +++ b/dashy/icons-temp/policeman.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dashy/icons-temp/root.png b/dashy/icons-temp/root.png new file mode 100644 index 0000000..3d4a1cb Binary files /dev/null and b/dashy/icons-temp/root.png differ diff --git a/dashy/icons-temp/security.svg b/dashy/icons-temp/security.svg new file mode 100644 index 0000000..c803155 --- /dev/null +++ b/dashy/icons-temp/security.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dashy/icons-temp/sheetable.jpeg b/dashy/icons-temp/sheetable.jpeg new file mode 100644 index 0000000..e618949 Binary files /dev/null and b/dashy/icons-temp/sheetable.jpeg differ diff --git a/dashy/icons-temp/sheetable.png b/dashy/icons-temp/sheetable.png new file mode 100644 index 0000000..d17d177 Binary files /dev/null and b/dashy/icons-temp/sheetable.png differ diff --git a/dashy/icons-temp/shield-user.svg b/dashy/icons-temp/shield-user.svg new file mode 100644 index 0000000..82fa67d --- /dev/null +++ b/dashy/icons-temp/shield-user.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dashy/icons-temp/software-development.png b/dashy/icons-temp/software-development.png new file mode 100644 index 0000000..f44be46 Binary files /dev/null and b/dashy/icons-temp/software-development.png differ diff --git a/dashy/icons-temp/software-development.psd b/dashy/icons-temp/software-development.psd new file mode 100644 index 0000000..a39f6e0 Binary files /dev/null and b/dashy/icons-temp/software-development.psd differ diff --git a/dashy/icons-temp/songkong.jpeg b/dashy/icons-temp/songkong.jpeg new file mode 100644 index 0000000..d6add58 Binary files /dev/null and b/dashy/icons-temp/songkong.jpeg differ diff --git a/dashy/icons-temp/songkong.png b/dashy/icons-temp/songkong.png new file mode 100644 index 0000000..fecd58d Binary files /dev/null and b/dashy/icons-temp/songkong.png differ diff --git a/dashy/icons-temp/static-web-server.png b/dashy/icons-temp/static-web-server.png new file mode 100644 index 0000000..0daeb08 Binary files /dev/null and b/dashy/icons-temp/static-web-server.png differ diff --git a/dashy/icons-temp/static-web-server.psd b/dashy/icons-temp/static-web-server.psd new file mode 100644 index 0000000..a42b588 Binary files /dev/null and b/dashy/icons-temp/static-web-server.psd differ diff --git a/dashy/icons-temp/traffic-cone.svg b/dashy/icons-temp/traffic-cone.svg new file mode 100644 index 0000000..d04ea31 --- /dev/null +++ b/dashy/icons-temp/traffic-cone.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/dashy/icons-temp/video-camera.svg b/dashy/icons-temp/video-camera.svg new file mode 100644 index 0000000..e7b8f45 --- /dev/null +++ b/dashy/icons-temp/video-camera.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dashy/icons-temp/web-server.svg b/dashy/icons-temp/web-server.svg new file mode 100644 index 0000000..2636aea --- /dev/null +++ b/dashy/icons-temp/web-server.svg @@ -0,0 +1 @@ +web-server \ No newline at end of file diff --git a/dashy/stacks/.dashy.env b/dashy/stacks/.dashy.env new file mode 100644 index 0000000..804e3e4 --- /dev/null +++ b/dashy/stacks/.dashy.env @@ -0,0 +1,7 @@ + +NODE_ENV=production +PUID=${PUID} +PGID=${PGID} + +VUE_APP_pihole_ip=${VUE_APP_pihole_ip} +VUE_APP_pihole_key=${VUE_APP_pihole_key} \ No newline at end of file diff --git a/dashy/stacks/.env b/dashy/stacks/.env new file mode 100644 index 0000000..c3d73c0 --- /dev/null +++ b/dashy/stacks/.env @@ -0,0 +1,22 @@ +################################################################ +APPLICATION_NAME=dashy + +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +PUID=3057 +PGID=3058 +DOMAINNAME=sthome.org +DNS_RESOLVER=sthomeresolver + +################################################################ + +WEBUI_PORT=8080 + +VUE_APP_pihole_ip=https://pihole.sthome.org +VUE_APP_pihole_key=48ab5845603098040b5d2455c2600cf14b643424f508d5aa30bb884ac11f55c3 \ No newline at end of file diff --git a/dashy/stacks/compose.yml b/dashy/stacks/compose.yml new file mode 100644 index 0000000..16c3df0 --- /dev/null +++ b/dashy/stacks/compose.yml @@ -0,0 +1,52 @@ +networks: + traefik-net: + external: true + +services: + dashy: + image: lissy93/dashy + # To build from source, replace 'image: lissy93/dashy' with 'build: .' + # build: . + env_file: .dashy.env + restart: unless-stopped + healthcheck: + test: ['CMD', 'node', '/app/services/healthcheck'] + interval: 1m30s + timeout: 10s + retries: 3 + start_period: 40s + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/config/config.yml:/app/user-data/conf.yml" + - "${DATADIR}/config:/app/user-data" + - "${DATADIR}/appdata/icons:/app/user-data/item-icons/" + networks: + - traefik-net + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http service + # ------------ + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http middlewares + # ---------------- + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/${APPLICATION_NAME}.txt" + # + # http routers + # ------------ + # http://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-redirect@file" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # https://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders@file" + # - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" \ No newline at end of file diff --git a/dashy/~$dashboard.xlsx b/dashy/~$dashboard.xlsx new file mode 100644 index 0000000..9b25dc2 Binary files /dev/null and b/dashy/~$dashboard.xlsx differ diff --git a/digikam/digikam_jm.txt b/digikam/digikam_jm.txt new file mode 100644 index 0000000..c347655 --- /dev/null +++ b/digikam/digikam_jm.txt @@ -0,0 +1,94 @@ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: digikam +Username: digikam +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +digikam UID: 3044 +digikam GID: 3043 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*digikam" +# create following dataset if not present +zfs create SSD1/docker/data/digikam +zfs create SSD1/docker/data/digikam/config +zfs create SSD1/docker/data/digikam/mariadb +chown -R digikam:digikam /mnt/SSD1/docker/data/digikam +chown -R mariadb:mariadb /mnt/SSD1/docker/data/digikam/mariadb + +Create foldera +-------------- +mkdir -p /mnt/SSD1/docker/stacks/digikam/secrets + +If not done already, add mapping for media in jail config +--------------------------------------------------------- +In this example: the folder where media is stored is /mnt/stpool1/NData1/Media +On Truenas shell: +jlmkr edit docker +Add the following args to "systemd_nspawn_user_args": +--bind='/mnt/stpool1/NData1/Media:/mnt/media' + +If not done already, set ACL permissions for media to be accessible by media group +---------------------------------------------------------------------------------- +On Truenas shell: +# read and note acl entries +getfacl /mnt/stpool1/NData1 +getfacl /mnt/stpool1/NData1/Media +# set read and execute permissions for media group on parent folder +setfacl -m g:media:5 /mnt/stpool1/NData1 +# set full permissions for media group on Media folder recursively +setfacl -R -m g:media:7 /mnt/stpool1/NData1/Media +# modify defaults recursively +setfacl -R -d -m g:media:7 /mnt/stpool1/NData1/Media +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in digikam folder, enter: +./cp2nas 192.168.2.2 +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/digikam/ +# This should copy stacks folder to /mnt/SSD1/docker/stacks/digikam + +Create secrets +-------------- +In Truenas shell: +cd /mnt/SSD1/docker/stacks/digikam/secrets +echo -n 'your_postgresql_database_name' > /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_database_name +echo -n 'your_postgresql_username' > /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_username +openssl rand 36 | base64 -w 0 | sed 's/[\$,\#,/,+,=]//g' | cut -c -32 | tr -d '\n' > /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_password +openssl rand 60 | base64 -w 0 | sed 's/[\$,\#,/,+,=]//g' | cut -c -56 | tr -d '\n' > /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_root_password +chown -R digikam:digikam /mnt/SSD1/docker/stacks/digikam/secrets/ +chmod -R 400 /mnt/SSD1/docker/stacks/digikam/secrets/ +# read existing acl permissions, if any +getfacl /mnt/SSD1/docker/stacks/digikam/secrets +# set acl permissions +setfacl -m u:mariadb:4 /mnt/SSD1/docker/stacks/digikam/secrets +setfacl -m u:mariadb:4 /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_root_password +setfacl -m u:mariadb:4 /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_password +setfacl -m u:mariadb:4 /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_username +setfacl -m u:mariadb:4 /mnt/SSD1/docker/stacks/digikam/secrets/digikam_mariadb_database_name +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R +# to list secrets in secrets dir +cd /mnt/SSD1/docker/stacks/digikam/secrets +for i in $(ls -1); do echo $i = `cat $i`; done | sort + +To open container shell +------------------------ +docker exec -it digikam-mariadb-1 bash + +To log into database from container shell +----------------------------------------- +mariadb -u root -p digikam +# Enter root password diff --git a/digikam/stacks/.digikam.env b/digikam/stacks/.digikam.env new file mode 100644 index 0000000..bf3b8ea --- /dev/null +++ b/digikam/stacks/.digikam.env @@ -0,0 +1,12 @@ + +PUID=${PUID} +PGID=${MEDIA_PGID} +TZ=${TZ} + +# POSTGRES_HOST=${POSTGRES_DB_HOST} +# POSTGRES_DB_PORT=${POSTGRES_DB_PORT} +# POSTGRES_DB_FILE=${POSTGRES_DB_FILE} +# POSTGRES_USER_FILE=${POSTGRES_USER_FILE} +# POSTGRES_PASSWORD_FILE=${POSTGRES_PASSWORD_FILE} +# DIGIKAM_ADMIN_PASSWORD_FILE=/run/secrets/digikam_admin_password +# DIGIKAM_ADMIN_USER_FILE=/run/secrets/digikam_admin_username diff --git a/digikam/stacks/.env b/digikam/stacks/.env new file mode 100644 index 0000000..816fb6d --- /dev/null +++ b/digikam/stacks/.env @@ -0,0 +1,27 @@ + +APPLICATION_NAME=digikam + +MEDIADIR=/mnt/stpool1/NData1/Media +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +PUID=3044 +PGID=3043 +MEDIA_PGID=3017 +MDB_PUID=3059 +MDB_PGID=3060 + +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org +WEBUI_PORT=3000 + +MARIADB_DB_PORT=3306 +# MARIADB_DB_HOST=digikam_mariadb +MARIADB_DB_NAME_FILE=/run/secrets/digikam_mariadb_database_name +MARIADB_USER_FILE=/run/secrets/digikam_mariadb_username +MARIADB_PASSWORD_FILE=/run/secrets/digikam_mariadb_password +MARIADB_ROOT_PASSWORD_FILE=/run/secrets/digikam_mariadb_root_password + diff --git a/digikam/stacks/.mariadb.env b/digikam/stacks/.mariadb.env new file mode 100644 index 0000000..f3701a5 --- /dev/null +++ b/digikam/stacks/.mariadb.env @@ -0,0 +1,12 @@ + +PUID=${MDB_PUID} +PGID=${MDB_PGID} +TZ=${TZ} + +MARIADB_ROOT_PASSWORD_FILE=${MARIADB_ROOT_PASSWORD_FILE} +MARIADB_DATABASE_FILE=${MARIADB_DB_NAME_FILE} +MARIADB_USER_FILE=${MARIADB_USER_FILE} +MARIADB_PASSWORD_FILE=${MARIADB_PASSWORD_FILE} + +# REMOTE_SQL=http://URL1/your.sql,https://URL2/your.sql + diff --git a/digikam/stacks/compose.yml b/digikam/stacks/compose.yml new file mode 100644 index 0000000..f8a9f45 --- /dev/null +++ b/digikam/stacks/compose.yml @@ -0,0 +1,99 @@ +name: digikam + +secrets: + digikam_mariadb_database_name: + file: ${SECRETSDIR}/digikam_mariadb_database_name + digikam_mariadb_username: + file: ${SECRETSDIR}/digikam_mariadb_username + digikam_mariadb_password: + file: ${SECRETSDIR}/digikam_mariadb_password + digikam_mariadb_root_password: + file: ${SECRETSDIR}/digikam_mariadb_root_password + +networks: + traefik-net: + external: true + digikam-net: + external: true + +services: + digikam: + image: lscr.io/linuxserver/digikam:latest + hostname: ${APPLICATION_NAME} + env_file: .digikam.env + restart: unless-stopped + depends_on: + - mariadb + # https://github.com/linuxserver/docker-baseimage-kasmvnc +# deploy: +# resources: +# reservations: +# devices: +# - driver: nvidia +# count: 1 +# #device_ids: +# # - "GPU-b9bf37c1-f8c9-201c-3456-0aa35381be42" +# capabilities: [compute,video,graphics,utility] + volumes: + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/config:/config" + - "${MEDIADIR}/Pictures:/config/Pictures" + networks: + - traefik-net + - digikam-net + +# https://github.com/linuxserver/docker-baseimage-kasmvnc#lossless +# nginx config +# add_header 'Cross-Origin-Embedder-Policy' 'require-corp'; +# add_header 'Cross-Origin-Opener-Policy' 'same-origin'; +# add_header 'Cross-Origin-Resource-Policy' 'same-site'; +# +# trying out following to see if they are working traefik equivalents with inspiration from https://community.traefik.io/t/setting-cross-origin-headers/22239/2 +# https://doc.traefik.io/traefik/middlewares/http/headers/ +# labels: +# - "traefik.http.middlewares.middleware-cross-origin.headers.customResponseHeaders.Cross-Origin-Embedder-Policy=require-corp" +# - "traefik.http.middlewares.middleware-cross-origin.headers.customResponseHeaders.Cross-Origin-Opener-Policy=same-origin" +# - "traefik.http.middlewares.middleware-cross-origin.headers.customResponseHeaders.Cross-Origin-Resource-Policy=same-site" + + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.permanent=true" + - "traefik.http.middlewares.${APPLICATION_NAME}-cross-origin.headers.customResponseHeaders.Cross-Origin-Embedder-Policy=require-corp" + - "traefik.http.middlewares.${APPLICATION_NAME}-cross-origin.headers.customResponseHeaders.Cross-Origin-Opener-Policy=same-origin" + - "traefik.http.middlewares.${APPLICATION_NAME}-cross-origin.headers.customResponseHeaders.Cross-Origin-Resource-Policy=same-site" + # + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=${APPLICATION_NAME}-https-redirect" + # + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=sthomeresolver" + # + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-cross-origin" + # + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + + mariadb: + image: mariadb:latest + restart: unless-stopped + env_file: .mariadb.env + hostname: mariadb + volumes: + - "${DATADIR}/mariadb:/config" + secrets: + - digikam_mariadb_database_name + - digikam_mariadb_username + - digikam_mariadb_password + - digikam_mariadb_root_password + networks: + - digikam-net + diff --git a/diun/stacks/.diun.env b/diun/stacks/.diun.env new file mode 100644 index 0000000..dd520e1 --- /dev/null +++ b/diun/stacks/.diun.env @@ -0,0 +1,34 @@ +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} +DIUN_WATCH_WORKERS=20 +DIUN_WATCH_SCHEDULE="0 */6 * * *" +DIUN_WATCH_JITTER=30s +DIUN_PROVIDERS_DOCKER=true + + +DIUN_NOTIF_MQTT_SCHEME=mqtt +DIUN_NOTIF_MQTT_HOST=mqtt.sthome.org +DIUN_NOTIF_MQTT_PORT=1883 +DIUN_NOTIF_MQTT_USERNAME=mqtt_user +# DIUN_NOTIF_MQTT_USERNAMEFILE +DIUN_NOTIF_MQTT_PASSWORD=Saterdag!32# +# DIUN_NOTIF_MQTT_PASSWORDFILE +DIUN_NOTIF_MQTT_CLIENT=diun +DIUN_NOTIF_MQTT_TOPIC=docker/diun +DIUN_NOTIF_MQTT_QOS=0 + + +# DIUN_NOTIF_MAIL_HOST= +# DIUN_NOTIF_MAIL_PORT= +# DIUN_NOTIF_MAIL_SSL= +# DIUN_NOTIF_MAIL_INSECURESKIPVERIFY= +# DIUN_NOTIF_MAIL_LOCALNAME= +# DIUN_NOTIF_MAIL_USERNAME= +# DIUN_NOTIF_MAIL_USERNAMEFILE= +# DIUN_NOTIF_MAIL_PASSWORD= +# DIUN_NOTIF_MAIL_PASSWORDFILE= +# DIUN_NOTIF_MAIL_FROM= +# DIUN_NOTIF_MAIL_TO= # comma separated +# DIUN_NOTIF_MAIL_TEMPLATETITLE={{ .Entry.Image }} {{ if (eq .Entry.Status "new") }}is available{{ else }}has been updated{{ end }} +# DIUN_NOTIF_MAIL_TEMPLATEBODY= diff --git a/diun/stacks/.env b/diun/stacks/.env new file mode 100644 index 0000000..79bc7d1 --- /dev/null +++ b/diun/stacks/.env @@ -0,0 +1,18 @@ +################################################################ +APPLICATION_NAME=diun + +DOCKERDIR=/mnt/SSD1/docker + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +PUID=3062 +PGID=3063 +DOMAINNAME=sthome.org +DNS_RESOLVER=sthomeresolver + +################################################################ + diff --git a/diun/stacks/.socket-proxy.env b/diun/stacks/.socket-proxy.env new file mode 100644 index 0000000..97691c1 --- /dev/null +++ b/diun/stacks/.socket-proxy.env @@ -0,0 +1,36 @@ +# +# environment variables for socket-proxy +# + +LOG_LEVEL=info # debug,info,notice,warning,err,crit,alert,emerg + +## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.). +### 0 to revoke access. +### 1 to grant access. +## Granted by Default +EVENTS=1 +PING=1 +VERSION=1 +## Revoked by Default +### Security critical +AUTH=0 +SECRETS=0 +POST=1 # Watchtower +### Not always needed +BUILD=0 +COMMIT=0 +CONFIGS=0 +CONTAINERS=1 # Traefik, portainer, etc. +DISTRIBUTION=0 +EXEC=0 +IMAGES=1 # Portainer +INFO=1 # Portainer +NETWORKS=1 # Portainer +NODES=0 +PLUGINS=0 +SERVICES=1 # Portainer +SESSION=0 +SWARM=0 +SYSTEM=0 +TASKS=1 # Portainer +VOLUMES=1 # Portainer \ No newline at end of file diff --git a/diun/stacks/compose.yml b/diun/stacks/compose.yml new file mode 100644 index 0000000..ba5e30c --- /dev/null +++ b/diun/stacks/compose.yml @@ -0,0 +1,50 @@ +name: diun + +networks: +# socket_proxy: +# driver: bridge +# driver_opts: +# com.docker.network.bridge.name: "br-diun_sx" + traefik-net: + external: true + +services: + diun: + image: crazymax/diun:latest + command: serve + env_file: .diun.env +# depends_on: +# - socket-proxy # Comment out if not using socket-proxy +# environment: +# - DOCKER_HOST=tcp://diun_socket-proxy:2375 + networks: + - traefik-net +# - socket_proxy + volumes: + - "${DATADIR}/appdata:/data" + - "/var/run/docker.sock:/var/run/docker.sock" + labels: + - "diun.enable=true" + restart: always + +############################################################### +# socket-proxy: +# image: tecnativa/docker-socket-proxy:0.2.0 #0.1.2 +# hostname: diun_socket-proxy +# restart: unless-stopped +# env_file: .socket-proxy.env +# security_opt: +# - no-new-privileges=true +# networks: +# - socket_proxy +# privileged: true # true for VM. false for unprivileged LXC container. +# #depends_on: +# # - traefik +## ports: +## - "127.0.0.1:2375:2375" +# volumes: +# - "/var/run/docker.sock:/var/run/docker.sock:ro" +# # the following bind is to persist the non-zero setting of backend docker-events.timeout server +## - type: bind +## source: "${DATADIR}/haproxy/haproxy.cfg.template" +## target: /usr/local/etc/haproxy/haproxy.cfg.template \ No newline at end of file diff --git a/emby/emby_jm.txt b/emby/emby_jm.txt new file mode 100644 index 0000000..f28f959 --- /dev/null +++ b/emby/emby_jm.txt @@ -0,0 +1,83 @@ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: emby +Username: emby +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +emby UID: 3017 +emby GID: 3016 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*emby" +# create following dataset if not present +zfs create SSD1/docker/data/emby/config +chown -R emby:emby /mnt/SSD1/docker/data/emby + +Create stacks folder +--------------------- +mkdir -p /mnt/SSD1/docker/stacks/emby + +If not done already, add mapping for media in jail config +--------------------------------------------------------- +In this example: the folder where media is stored is /mnt/stpool1/NData1/Media +On Truenas shell: +jlmkr edit docker +Add the following args to "systemd_nspawn_user_args": +--bind='/mnt/stpool1/NData1/Media:/mnt/media' + +If not done already, set ACL permissions for media to be accessible by media group +---------------------------------------------------------------------------------- +On Truenas shell: +# read and note acl entries +getfacl /mnt/stpool1/NData1 +getfacl /mnt/stpool1/NData1/Media +# set read and execute permissions for media group on parent folder +setfacl -m g:media:5 /mnt/stpool1/NData1 +# set full permissions for media group on Media folder recursively +setfacl -R -m g:media:7 /mnt/stpool1/NData1/Media +# modify defaults recursively +setfacl -R -d -m g:media:7 /mnt/stpool1/NData1/Media +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in emby folder, enter: +./cp2nas 192.168.2.2 +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/emby/ +# This should copy stacks folder to /mnt/SSD1/docker/stacks/emby + +Migrating data from old emby media server (source) to newly installed one (target) +---------------------------------------------------------------------------------- +# Stop old/source emby media server +heavyscript app --stop emby +# Stop new/target emby media server +# On Dockge, select emby and click stop +# Copy the source Library to target folder (this might take a while): +cp -pr /mnt/stpool1/apps/emby/* /mnt/SSD1/docker/data/emby/config/ +chown -R emby:emby /mnt/SSD1/docker/data/emby/config + +Managing library files +---------------------- +Try and keep the mount folders for the media the same as that of the old media server +However, if you choose to have a different mount: +For example, +If the old media server mapped to /Media and the new one now maps to /data, then you will have to modify the media folders in emby settings to reflect the new mount. +Open emby, click on the spanner/wrench and select Manage->Libraries +Go through all the libraries items, adding new media folders and removing those that were replaced +This may take some time (depends on library size) + + + + diff --git a/emby/stacks/.emby.env b/emby/stacks/.emby.env new file mode 100644 index 0000000..da5109e --- /dev/null +++ b/emby/stacks/.emby.env @@ -0,0 +1,14 @@ +# +# environment variables for emby +# +PUID=${PUID} +PGID=${MEDIA_GID} +TZ=Africa/Johannesburg +PORT=${WEBUI_PORT} + +NVIDIA_VISIBLE_DEVICES=all + + + + + diff --git a/emby/stacks/.env b/emby/stacks/.env new file mode 100644 index 0000000..11a02a2 --- /dev/null +++ b/emby/stacks/.env @@ -0,0 +1,23 @@ +# +# values to be used for substitution by docker compose in compose.yml AND .*.env files +# +APPLICATION_NAME=emby + +MEDIADIR=/mnt/stpool1/NData1/Media +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +CT_MEDIA=/Media + +MEDIA_GID=3017 +PUID=3017 +PGID=3016 +DOMAINNAME=sthome.org +WEBUI_PORT=8096 + +GPU_DEVICE_ID=GPU-b9bf37c1-f8c9-201c-3456-0aa35381be42 + + diff --git a/emby/stacks/compose.yml b/emby/stacks/compose.yml new file mode 100644 index 0000000..36377f0 --- /dev/null +++ b/emby/stacks/compose.yml @@ -0,0 +1,66 @@ +name: emby + +networks: + traefik-net: + external: true + +services: + emby: + image: lscr.io/linuxserver/emby:latest + hostname: "${APPLICATION_NAME}" + env_file: .emby.env + group_add: + - "${MEDIA_GID}" # not really needed if we have it as the primary gid + restart: unless-stopped + # this deploy section requires the installation of the nvidia-container-toolkit; comment out if the toolkit is not installed + deploy: + resources: + reservations: + devices: + - driver: nvidia + #count: 1 + device_ids: + - "${GPU_DEVICE_ID}" + capabilities: [gpu] + volumes: + - /etc/localtime:/etc/localtime:ro + - ${DATADIR}/config:/config + - ${MEDIADIR}:${CT_MEDIA} + networks: + - traefik-net + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http services + # ------------- + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http routers + # ------------ + # limit router to web ":80" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-redirect@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders@file" + # tls + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # apply tls options + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + + + diff --git a/external/ext-proxmox.yml b/external/ext-proxmox.yml new file mode 100644 index 0000000..188e5ec --- /dev/null +++ b/external/ext-proxmox.yml @@ -0,0 +1,57 @@ +# NOT WORKING +# pve.sthome.org returns HTTP 500 - Internal Server Error +# Use http://proxmox-local.sthome.org:8006 to access pve +# +# +# external service +# https://doc.traefik.io/traefik/providers/file/ + +#http: +# # +# # http routers +# # ------------ +# routers: +# proxmox-rtr: +# entryPoints: ["web"] +# rule: "Host(`proxmox.sthome.org`)&& PathPrefix(`/`) || Host(`pve.sthome.org`)" +# middlewares: +## - proxmox-auth +# - http-mw-rateLimit-secureHeaders-redirect@file # proxmox-https-redirect +# service: "ext-proxmox-svc" +# +# proxmox-secure-rtr: +# entryPoints: ["websecure"] +# rule: "Host(`proxmox.sthome.org`)&& PathPrefix(`/`) || Host(`pve.sthome.org`)" +# tls: +# certresolver: "solver-dns" +# domains: +# - main: "sthome.org" +# sans: +# - "*.sthome.org" +## middlewares: +## - proxmox-auth +# - http-mw-rateLimit-secureHeaders@file # + # service: "ext-proxmox-svc" +# # +# # http middlewares +# # ---------------- +# middlewares: +## proxmox-auth: +## basicauth: +## usersfile: "/mnt/users/cctv.txt" +# proxmox-https-redirect: +# redirectscheme: +# scheme: https +# permanent: true +# # +# # http service +# # ------------ +# # https://doc.traefik.io/traefik/routing/services/ +# services: +# ext-proxmox-svc: +# loadBalancer: +# servers: +## - url: "https://proxmox-local.sthome.org:8006" # requires local dns, i.e. 10.0.0.1, to be first nameserver in truenas and in docker /etc/resolv.conf +# - url: "https://10.0.0.22:8006" # safest to use ip address, with reservation in dhcp server +## - url: "http://10.0.0.30:80" # test with WSTAT +# passHostHeader: true \ No newline at end of file diff --git a/external/ext-truenas.yml b/external/ext-truenas.yml new file mode 100644 index 0000000..012ac49 --- /dev/null +++ b/external/ext-truenas.yml @@ -0,0 +1,50 @@ +# external service +# https://doc.traefik.io/traefik/providers/file/ +# not working +#http: +# # +# # http routers +# # ------------ +# routers: +# truenas-rtr: +# entryPoints: +# - "web" +# rule: "Host(`truenas.sthome.org`)&& PathPrefix(`/`)" +# tls: +# certresolver: "solver-dns" +# middlewares: +# - http-mw-rateLimit-secureHeaders-redirect@file # truenas-https-redirect +# service: "ext-truenas-svc" +# +# truenas-secure-rtr: +# entryPoints: +# - "websecure" +# rule: "Host(`truenas.sthome.org`)&& PathPrefix(`/`)" +# tls: +# certresolver: "solver-dns" +# domains: +# - main: "sthome.org" +# sans: +# - "*.sthome.org" +# - "truenas.sthome.org" +# middlewares: +# - http-mw-rateLimit-secureHeaders@file +# service: "ext-truenas-svc" +# # +# # http middlewares +# # ---------------- +# middlewares: +# truenas-https-redirect: +# redirectscheme: +# scheme: https +# permanent: true +# # +# # http service +# # ------------ +# # https://doc.traefik.io/traefik/routing/services/ +# services: +# ext-truenas-svc: +# loadBalancer: +# servers: +# - url: "http://10.0.0.20:443" +# passHostHeader: true \ No newline at end of file diff --git a/external/traefik-rules/ext-cctv.yml b/external/traefik-rules/ext-cctv.yml new file mode 100644 index 0000000..ce8014e --- /dev/null +++ b/external/traefik-rules/ext-cctv.yml @@ -0,0 +1,38 @@ +# external service +# https://doc.traefik.io/traefik/providers/file/ + +http: +# +# http routers +# ------------ + routers: + cctv-rtr: + entryPoints: + - "web" + rule: "Host(`cctv.sthome.org`)&& PathPrefix(`/`)" + middlewares: + + - http-mw-rateLimit-secureHeaders-redirect@file + service: "ext-cctv-svc" + + cctv-secure-rtr: + entryPoints: + - "websecure" + rule: "Host(`cctv.sthome.org`)&& PathPrefix(`/`)" + tls: + certresolver: "solver-dns" + options: tls-options@file + middlewares: + + - http-mw-rateLimit-secureHeaders@file + service: "ext-cctv-svc" + # +# http service +# ------------ +# https://doc.traefik.io/traefik/routing/services/ + services: + ext-cctv-svc: + loadBalancer: + servers: + - url: "http://10.0.0.10:80" # safest to use ip address, with reservation in dhcp server + passHostHeader: true \ No newline at end of file diff --git a/external/traefik-rules/ext-frigate.yml b/external/traefik-rules/ext-frigate.yml new file mode 100644 index 0000000..e5e9adf --- /dev/null +++ b/external/traefik-rules/ext-frigate.yml @@ -0,0 +1,59 @@ +# external service +# https://doc.traefik.io/traefik/providers/file/ + +http: +# +# http routers +# ------------ + routers: + frigate-rtr: + entryPoints: + - "web" + rule: "Host(`frigate.sthome.org`)&& PathPrefix(`/`)" + middlewares: + - frigate-auth + - http-mw-rateLimit-secureHeaders-redirect@file + service: "ext-frigate-svc" + + frigate-secure-rtr: + entryPoints: + - "websecure" + rule: "Host(`frigate.sthome.org`)&& PathPrefix(`/`)" + tls: + certresolver: "solver-dns" + options: tls-options@file + middlewares: + - frigate-auth + - http-mw-rateLimit-secureHeaders@file + service: "ext-frigate-svc" + + frigate-secure-status-rtr: + entryPoints: + - "websecure" + rule: "Host(`frigate.sthome.org`)&& PathPrefix(`/stats`)" + tls: + certresolver: "solver-dns" + options: tls-options@file + service: "ext-frigate-svc" +# +# http middlewares +# ---------------- + middlewares: + frigate-auth: + basicauth: + usersfile: "/mnt/users/frigate.txt" +# frigate-https-redirect: +# redirectscheme: +# scheme: https +# permanent: true + +# +# http service +# ------------ +# https://doc.traefik.io/traefik/routing/services/ + services: + ext-frigate-svc: + loadBalancer: + servers: + - url: "http://10.0.0.51:5000" # safest to use ip address, with reservation in dhcp server + passHostHeader: true \ No newline at end of file diff --git a/external/traefik-users/cctv.txt b/external/traefik-users/cctv.txt new file mode 100644 index 0000000..2084684 --- /dev/null +++ b/external/traefik-users/cctv.txt @@ -0,0 +1,5 @@ +admin:$2y$05$djOyLnsk5p1.wcCLJCXpcehznR3cc04otaSlpED3fSRC9EpRGDkMC +chris:$2y$05$FSl7QIqo.VMe69nm8K.Dv.O05Gi6oad.2qY7oKjgqbPa4eBPintbK +Chris:$2y$05$8r6M8zr0MFIiDLUm1vP1Ee0AP8kMJtDsw4zezFeSDVlWeEOkwuBuC +home:$2y$05$VjkUjMGVdxMn3N/rMK8nBuh1jAUfezo8i4167enEg7i9Xl45cVQGi +Home:$2y$05$JP8tB1nkPA8tbhEnhGV6teke.X87eFX4V9hi9qa2ArLISJ4Ksf2ca \ No newline at end of file diff --git a/external/traefik-users/frigate.txt b/external/traefik-users/frigate.txt new file mode 100644 index 0000000..2084684 --- /dev/null +++ b/external/traefik-users/frigate.txt @@ -0,0 +1,5 @@ +admin:$2y$05$djOyLnsk5p1.wcCLJCXpcehznR3cc04otaSlpED3fSRC9EpRGDkMC +chris:$2y$05$FSl7QIqo.VMe69nm8K.Dv.O05Gi6oad.2qY7oKjgqbPa4eBPintbK +Chris:$2y$05$8r6M8zr0MFIiDLUm1vP1Ee0AP8kMJtDsw4zezFeSDVlWeEOkwuBuC +home:$2y$05$VjkUjMGVdxMn3N/rMK8nBuh1jAUfezo8i4167enEg7i9Xl45cVQGi +Home:$2y$05$JP8tB1nkPA8tbhEnhGV6teke.X87eFX4V9hi9qa2ArLISJ4Ksf2ca \ No newline at end of file diff --git a/fireflyiii/fireflyiii_jm.txt b/fireflyiii/fireflyiii_jm.txt new file mode 100644 index 0000000..3a049a4 --- /dev/null +++ b/fireflyiii/fireflyiii_jm.txt @@ -0,0 +1,152 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: fireflyiii +Username: firefly3 +Disable Password: +Data: +Objects: +Check public to select all objects +Click Backup +After successfull backup, close pgAdmin on truenas + +Migrating database +------------------ +# Refresh Dockge window/tab and start fireflyiii in Dockge +# After successfull startup of fireflyiii and postgress, stop fireflyiii from docker cmd line +docker stop firefly +# In truenas shell +# copy back up file(s) to fireflyiii backups folder +cp -vr /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) /mnt/SSD1/docker/data/fireflyiii/pgbackups #replace $(date -I) with date when backup was made if not today +jlmkr shell docker +cd /mnt/data/fireflyiii +# remove all files/folders from pgdata; if any are already in this folder, move it to another folder before executing next command +rm -r /mnt/data/fireflyiii/pgdata/* +# Start fireflyiii with Dockge, then: +docker stop firefly +docker exec firefly_postgresql psql -U firefly -d postgres -c "DROP DATABASE \"firefly\";" +docker exec firefly_postgresql psql -U firefly -d postgres -c "CREATE DATABASE \"firefly\";" +docker exec firefly_postgresql psql -U firefly -d firefly -f /mnt/backups/$(date -I)/fireflyiii-backup.sql +docker start firefly + +Post startup if no migration was performed +------------------------------------------- +# https://docs.firefly-iii.org/references/faq/install/ +# The documentation mentions the following to initialise / seed the database on a clean install: +# In docker shell: +docker exec firefly php artisan migrate:refresh --seed --force +docker exec firefly php artisan firefly-iii:upgrade-database + +Stop truenas fireflyiii +----------------------- +# In truenas shell +heavyscript app --stop fireflyiii +# NB: Do NOT stop fireflyiii with truenas gui + +Troubleshooting +--------------- +# If you get persistent db authentication errors: +Ensure that the service name (name of the stanza), host name and container name of the postgresql container in the compose.yml file and the DB_HOST value in the .env file are all the same + +If you need to log into db +-------------------------- +docker exec -it firefly_postgresql bash +psql -U firefly -d firefly + + + diff --git a/fireflyiii/stacks/.env b/fireflyiii/stacks/.env new file mode 100644 index 0000000..46c5d34 --- /dev/null +++ b/fireflyiii/stacks/.env @@ -0,0 +1,41 @@ +PROJECT_NAME=fireflyiii # distinguish between fireflyiii and firefly +APPLICATION_NAME=firefly + +IMPORTER_NAME=firefly-importer + +MEDIADIR=/mnt/stpool1/NData1/Media +DOCKERDIR=/mnt/SSD1/docker + +STACKSDIR=${DOCKERDIR}/stacks/${PROJECT_NAME} +DATADIR=${DOCKERDIR}/data/${PROJECT_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org +WEBUI_PORT=8080 +IMPORTER_WEBUI_PORT=8080 + +PUID=3035 +PGID=3034 +TZ=Africa/Johannesburg + +FFIII_MAIL_PORT=25 +FFIII_FQDN=${APPLICATION_NAME}.${DOMAINNAME} +FFIII_IMPORTER_FQDN=${IMPORTER_NAME}.${DOMAINNAME} + +# secrets +FFIII_ACCESS_TOKEN_FILE=/run/secrets/fireflyiii_access_token +FFIII_APP_KEY_FILE=/run/secrets/fireflyiii_app_key +FFIII_MAP_DEFAULT_LAT_FILE=/run/secrets/fireflyiii_default_lat +FFIII_MAP_DEFAULT_LONG_FILE=/run/secrets/fireflyiii_default_long +FFIII_MAIL_DESTINATION_FILE=/run/secrets/fireflyiii_mail_destination +FFIII_MAIL_FROM_FILE=/run/secrets/fireflyiii_mail_from +FFIII_MAIL_HOST_FILE=/run/secrets/fireflyiii_mail_host +FFIII_MAIL_PASSWORD_FILE=/run/secrets/fireflyiii_mail_password +FFIII_MAIL_USERNAME_FILE=/run/secrets/fireflyiii_mail_username +FFIII_DB_NAME_FILE=/run/secrets/fireflyiii_postgresql_database +FFIII_DB_PASSWORD_FILE=/run/secrets/fireflyiii_postgresql_password +FFIII_DB_USER_FILE=/run/secrets/fireflyiii_postgresql_username +FFIII_SITE_OWNER_FILE=/run/secrets/fireflyiii_site_owner +FFIII_STATIC_CRON_TOKEN_FILE=/run/secrets/fireflyiii_static_cron_token + + diff --git a/fireflyiii/stacks/.firefly.env b/fireflyiii/stacks/.firefly.env new file mode 100644 index 0000000..5ec34dc --- /dev/null +++ b/fireflyiii/stacks/.firefly.env @@ -0,0 +1,325 @@ + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +# You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. +# Never set it to "testing". +APP_ENV=local + +# Set to true if you want to see debug information in error screens. +APP_DEBUG=false + +# This should be your email address. +# If you use Docker or similar, you can set this variable from a file by using SITE_OWNER_FILE +# The variable is used in some errors shown to users who aren't admin. +SITE_OWNER_FILE=${FFIII_SITE_OWNER_FILE} + +# The encryption key for your sessions. Keep this very secure. +# Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it. +# If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE +# +# Avoid the "#" character in your APP_KEY, it may break things. +# +APP_KEY_FILE=${FFIII_APP_KEY_FILE} + +# Firefly III will launch using this language (for new users and unauthenticated visitors) +# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang +# +# If text is still in English, remember that not everything may have been translated. +DEFAULT_LANGUAGE=en_US + +# The locale defines how numbers are formatted. +# by default this value is the same as whatever the language is. +DEFAULT_LOCALE=equal + +# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. +# Set it to ** and reverse proxies work just fine. +TRUSTED_PROXIES=** + +# The log channel defines where your log entries go to. +# Several other options exist. You can use 'single' for one big fat error log (not recommended). +# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. +# A rotating log option is 'daily', creates 5 files that (surprise) rotate. +# A cool option is 'papertrail' for cloud logging +# Default setting 'stack' will log to 'daily' and to 'stdout' at the same time. +LOG_CHANNEL=stack + +# Log level. You can set this from least severe to most severe: +# debug, info, notice, warning, error, critical, alert, emergency +# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably +# nothing will get logged, ever. +APP_LOG_LEVEL=notice + +# Audit log level. +# The audit log is used to log notable Firefly III events on a separate channel. +# These log entries may contain sensitive financial information. +# The audit log is disabled by default. +# +# To enable it, set AUDIT_LOG_LEVEL to "info" +# To disable it, set AUDIT_LOG_LEVEL to "emergency" +AUDIT_LOG_LEVEL=emergency + +# +# If you want, you can redirect the audit logs to another channel. +# Set 'audit_stdout', 'audit_syslog', 'audit_errorlog' to log to the system itself. +# Use audit_daily to log to a rotating file. +# Use audit_papertrail to log to papertrail. +# +# If you do this, the audit logs may be mixed with normal logs because the settings for these channels +# are often the same as the settings for the normal logs. +AUDIT_LOG_CHANNEL= + +# +# Used when logging to papertrail: +# Also used when audit logs log to papertrail: +# +PAPERTRAIL_HOST= +PAPERTRAIL_PORT= + +# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III +# For other database types, please see the FAQ: https://docs.firefly-iii.org/references/faq/install/#i-want-to-use-sqlite +# If you use Docker or similar, you can set these variables from a file by appending them with _FILE +# Use "pgsql" for PostgreSQL +# Use "mysql" for MySQL and MariaDB. +# Use "sqlite" for SQLite. +DB_CONNECTION=pgsql +DB_HOST=firefly_postgresql +DB_PORT=5432 +DB_DATABASE_FILE=${FFIII_DB_NAME_FILE} +DB_USERNAME_FILE=${FFIII_DB_USER_FILE} +DB_PASSWORD_FILE=${FFIII_DB_PASSWORD_FILE} +# leave empty or omit when not using a socket connection +DB_SOCKET= + +# MySQL supports SSL. You can configure it here. +# If you use Docker or similar, you can set these variables from a file by appending them with _FILE +MYSQL_USE_SSL=false +MYSQL_SSL_VERIFY_SERVER_CERT=true +# You need to set at least of these options +MYSQL_SSL_CAPATH=/etc/ssl/certs/ +MYSQL_SSL_CA= +MYSQL_SSL_CERT= +MYSQL_SSL_KEY= +MYSQL_SSL_CIPHER= + +# PostgreSQL supports SSL. You can configure it here. +# If you use Docker or similar, you can set these variables from a file by appending them with _FILE +PGSQL_SSL_MODE=prefer +PGSQL_SSL_ROOT_CERT=null +PGSQL_SSL_CERT=null +PGSQL_SSL_KEY=null +PGSQL_SSL_CRL_FILE=null + +# For postgresql 15 and up, setting this to public will no longer work as expected, because the +# 'public' schema is without grants. This can be worked around by having a super user grant those +# necessary privileges, but in security conscious setups that's not viable. +# You will need to set this to the schema you want to use. +PGSQL_SCHEMA=public + +# If you're looking for performance improvements, you could install memcached or redis +CACHE_DRIVER=file +SESSION_DRIVER=file + +# If you set either of the options above to 'redis', you might want to update these settings too +# If you use Docker or similar, you can set REDIS_HOST_FILE, REDIS_PASSWORD_FILE or +# REDIS_PORT_FILE to set the value from a file instead of from an environment variable + +# can be tcp or unix. http is not supported +REDIS_SCHEME=tcp + +# use only when using 'unix' for REDIS_SCHEME. Leave empty otherwise. +REDIS_PATH= + +# use only when using 'tcp' or 'http' for REDIS_SCHEME. Leave empty otherwise. +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 + +# Use only with Redis 6+ with proper ACL set. Leave empty otherwise. +REDIS_USERNAME= +REDIS_PASSWORD= + +# always use quotes and make sure redis db "0" and "1" exists. Otherwise change accordingly. +REDIS_DB="0" +REDIS_CACHE_DB="1" + +# Cookie settings. Should not be necessary to change these. +# If you use Docker or similar, you can set COOKIE_DOMAIN_FILE to set +# the value from a file instead of from an environment variable +# Setting samesite to "strict" may give you trouble logging in. +COOKIE_PATH="/" +COOKIE_DOMAIN= +COOKIE_SECURE=false +COOKIE_SAMESITE=lax + +# If you want Firefly III to email you, update these settings +# For instructions, see: https://docs.firefly-iii.org/how-to/firefly-iii/advanced/notifications/#email +# If you use Docker or similar, you can set these variables from a file by appending them with _FILE +MAIL_MAILER=log +MAIL_HOST_FILE=${FFIII_MAIL_HOST_FILE} +MAIL_PORT=${FFIII_MAIL_PORT} +MAIL_FROM_FILE=${FFIII_MAIL_FROM_FILE} +MAIL_USERNAME_FILE=${FFIII_MAIL_USERNAME_FILE} +MAIL_PASSWORD_FILE=${FFIII_MAIL_PASSWORD_FILE} +MAIL_ENCRYPTION=null +#MAIL_SENDMAIL_COMMAND= + +# Other mail drivers: +# If you use Docker or similar, you can set these variables from a file by appending them with _FILE +MAILGUN_DOMAIN= +MAILGUN_SECRET= + +# If you are on EU region in mailgun, use api.eu.mailgun.net, otherwise use api.mailgun.net +# If you use Docker or similar, you can set this variable from a file by appending it with _FILE +#MAILGUN_ENDPOINT=api.mailgun.net + +# If you use Docker or similar, you can set these variables from a file by appending them with _FILE +MANDRILL_SECRET= +SPARKPOST_SECRET= + +# Firefly III can send you the following messages. +SEND_ERROR_MESSAGE=true + +# These messages contain (sensitive) transaction information: +SEND_REPORT_JOURNALS=true + +# Set this value to true if you want to set the location of certain things, like transactions. +# Since this involves an external service, it's optional and disabled by default. +ENABLE_EXTERNAL_MAP=false + +# +# Enable or disable exchange rate conversion. This function isn't used yet by Firefly III +# +ENABLE_EXCHANGE_RATES=false + +# Set this value to true if you want Firefly III to download currency exchange rates +# from the internet. These rates are hosted by the creator of Firefly III inside +# an Azure Storage Container. +# Not all currencies may be available. Rates may be wrong. +ENABLE_EXTERNAL_RATES=false + +# The map will default to this location: +MAP_DEFAULT_LAT_FILE=${FFIII_MAP_DEFAULT_LAT_FILE} +MAP_DEFAULT_LONG_FILE=${FFIII_MAP_DEFAULT_LONG_FILE} +MAP_DEFAULT_ZOOM=6 + +# +# Some objects have room for an URL, like transactions and webhooks. +# By default, the following protocols are allowed: +# http, https, ftp, ftps, mailto +# +# To change this, set your preferred comma separated set below. +# Be sure to include http, https and other default ones if you need to. +# +VALID_URL_PROTOCOLS= + +# +# Firefly III authentication settings +# + +# +# Firefly III supports a few authentication methods: +# - 'web' (default, uses built in DB) +# - 'remote_user_guard' for Authelia etc +# Read more about these settings in the documentation. +# https://docs.firefly-iii.org/how-to/firefly-iii/advanced/authentication/ +# +# LDAP is no longer supported :( +# +AUTHENTICATION_GUARD=web + +# +# Remote user guard settings +# +AUTHENTICATION_GUARD_HEADER=REMOTE_USER +AUTHENTICATION_GUARD_EMAIL= + +# +# Firefly III generates a basic keypair for your OAuth tokens. +# If you want, you can overrule the key with your own (secure) value. +# It's also possible to set PASSPORT_PUBLIC_KEY_FILE or PASSPORT_PRIVATE_KEY_FILE +# if you're using Docker secrets or similar solutions for secret management +# +PASSPORT_PRIVATE_KEY= +PASSPORT_PUBLIC_KEY= + +# +# Extra authentication settings +# +CUSTOM_LOGOUT_URL= + +# You can disable the X-Frame-Options header if it interferes with tools like +# Organizr. This is at your own risk. Applications running in frames run the risk +# of leaking information to their parent frame. +DISABLE_FRAME_HEADER=false + +# You can disable the Content Security Policy header when you're using an ancient browser +# or any version of Microsoft Edge / Internet Explorer (which amounts to the same thing really) +# This leaves you with the risk of not being able to stop XSS bugs should they ever surface. +# This is at your own risk. +DISABLE_CSP_HEADER=false + +# If you wish to track your own behavior over Firefly III, set valid analytics tracker information here. +# Nobody uses this except for me on the demo site. But hey, feel free to use this if you want to. +# Do not prepend the TRACKER_URL with http:// or https:// +# The only tracker supported is Matomo. +# You can set the following variables from a file by appending them with _FILE: +#TRACKER_SITE_ID= +#TRACKER_URL= + +# +# Firefly III supports webhooks. These are security sensitive and must be enabled manually first. +# +ALLOW_WEBHOOKS=false + +# +# The static cron job token can be useful when you use Docker and wish to manage cron jobs. +# 1. Set this token to any 32-character value (this is important!). +# 2. Use this token in the cron URL instead of a user's command line token that you can find in /profile +# +# For more info: https://docs.firefly-iii.org/how-to/firefly-iii/advanced/cron/ +# +# You can set this variable from a file by appending it with _FILE +# +STATIC_CRON_TOKEN_FILE=${FFIII_STATIC_CRON_TOKEN_FILE} + +# You can fine tune the start-up of a Docker container by editing these environment variables. +# Use this at your own risk. Disabling certain checks and features may result in lots of inconsistent data. +# However if you know what you're doing you can significantly speed up container start times. +# Set each value to true to enable, or false to disable. + +# Set this to true to build all locales supported by Firefly III. +# This may take quite some time (several minutes) and is generally not recommended. +# If you wish to change or alter the list of locales, start your Docker container with +# `docker run -v locale.gen:/etc/locale.gen -e DKR_BUILD_LOCALE=true` +# and make sure your preferred locales are in your own locale.gen. +DKR_BUILD_LOCALE=false + +# Check if the SQLite database exists. Can be skipped if you're not using SQLite. +# Won't significantly speed up things. +#DKR_CHECK_SQLITE=true + +# Leave the following configuration vars as is. +# Unless you like to tinker and know what you're doing. +APP_NAME=FireflyIII +BROADCAST_DRIVER=log +QUEUE_DRIVER=sync +CACHE_PREFIX=firefly +PUSHER_KEY= +IPINFO_TOKEN= +PUSHER_SECRET= +PUSHER_ID= +DEMO_USERNAME= +DEMO_PASSWORD= + +# +# The v2 layout is very experimental. If it breaks you get to keep both parts. +# Be wary of data loss. +# +FIREFLY_III_LAYOUT=v1 + +# +# Please make sure this URL matches the external URL of your Firefly III installation. +# It is used to validate specific requests and to generate URLs in emails. +# +APP_URL=https://${FFIII_FQDN} \ No newline at end of file diff --git a/fireflyiii/stacks/.importer.env b/fireflyiii/stacks/.importer.env new file mode 100644 index 0000000..7bf4f8c --- /dev/null +++ b/fireflyiii/stacks/.importer.env @@ -0,0 +1,292 @@ +PUID=3035 +PGID=3034 +TZ=Africa/Johannesburg + +# Firefly Data Importer (FIDI) configuration file + +# Where is Firefly III? +# +# 1) Make sure you ADD http:// or https:// +# 2) Make sure you REMOVE any trailing slash from the end of the URL. +# 3) In case of Docker, refer to the internal IP of your Firefly III installation. +# +# Setting this value is not mandatory. But it is very useful. +# +# This variable can be set from a file if you append it with _FILE +# +FIREFLY_III_URL=https://${FFIII_FQDN} # connects via traefik websecure entrypoint + +# +# Imagine Firefly III can be reached at "http://172.16.0.2:8082" (internal Docker network or something). +# But you have a fancy URL: "https://personal-finances.bill.microsoft.com/" +# +# In those cases, you can overrule the URL so when the data importer links back to Firefly III, it uses the correct URL. +# +# 1) Make sure you ADD http:// or https:// +# 2) Make sure you REMOVE any trailing slash from the end of the URL. +# +# IF YOU SET THIS VALUE, YOU MUST ALSO SET THE FIREFLY_III_URL +# +# This variable can be set from a file if you append it with _FILE +# +VANITY_URL=https://${FFIII_FQDN} # connects via traefik websecure entrypoint + +# +# Set your Firefly III Personal Access Token (OAuth) +# You can create a Personal Access Token on the /profile page: +# go to the OAuth tab, then Personal Access Token and "Create token". +# +# - Do not use the "command line token". That's the WRONG one. +# - Do not use "APP_KEY" value from your Firefly III installation. That's the WRONG one. +# +# Setting this value is not mandatory. Instructions will follow if you omit this field. +# +# This variable can be set from a file if you append it with _FILE +# +FIREFLY_III_ACCESS_TOKEN_FILE=${FFIII_ACCESS_TOKEN_FILE} + +# +# You can also use a public client ID. This is available in Firefly III 5.4.0-alpha.3 and higher. +# This is a number (1, 2, 3). If you use the client ID, you can leave the access token empty and vice versa. +# +# This value is not mandatory to set. Instructions will follow if you omit this field. +# +# This variable can be set from a file if you append it with _FILE +# +FIREFLY_III_CLIENT_ID= + +# +# GoCardless information. +# The key and ID can be set from a file if you append it with _FILE +# +NORDIGEN_ID= +NORDIGEN_KEY= + +# +# If you want to use the GoCardless sandbox, set this to true. +# +NORDIGEN_SANDBOX=false + +# +# GoCardless has a rate limit in place. The data importer can wait it out, or exit. +# Valid values are "wait" or "exit" +# +RESPOND_TO_GOCARDLESS_LIMIT=wait + +# +# The data importer collects account details, which are currently unused. +# This is disabled, since it costs a lot of API calls. +# You can enable it if you want to. +# +GOCARDLESS_GET_ACCOUNT_DETAILS=false + +# +# The data importer also collects balances, which can be used for (manual) +# balance verification ("did the import go well?"). +# This is disabled by default, since it costs a lot of API calls. +# You can enable it if you want to. +# +GOCARDLESS_GET_BALANCE_DETAILS=false + +# +# Spectre information +# +# The ID and secret can be set from a file if you append it with _FILE +SPECTRE_APP_ID= +SPECTRE_SECRET= + +# +# Use cache. No need to do this. +# +USE_CACHE=false + +# +# If set to true, the data import will not complain about running into duplicates. +# This will give you cleaner import mails if you run regular imports. +# +# This means that the data importer will not import duplicates, but it will not complain about them either. +# +# This setting has no influence on the settings in your configuration(.json). +# +# Of course, if something goes wrong *because* the transaction is a duplicate you will +# NEVER know unless you start digging in your log files. So be careful with this. +# +IGNORE_DUPLICATE_ERRORS=false + +# +# If you set this to true, the importer will not complain about transactions that can't be found after they've +# been imported. This happens when rule on the Firefly III side deletes the transaction immediately after creating it. +# This can be useful when you have a rule that immediately deletes GoCardless' "pending" transactions. Setting this +# to true reduces some noise. +# +IGNORE_NOT_FOUND_TRANSACTIONS=false + +# +# Auto import settings. Due to security constraints, you MUST enable each feature individually. +# You must also set a secret. The secret is used for the web routes. +# +# The auto-import secret must be a string of at least 16 characters. +# Visit this page for inspiration: https://www.random.org/passwords/?num=1&len=16&format=html&rnd=new +# +# Submit it using ?secret=X +# +# This variable can be set from a file if you append it with _FILE +# +AUTO_IMPORT_SECRET= + +# +# Is the /autoimport even endpoint enabled? +# By default it's disabled, and the secret alone will not enable it. +# +CAN_POST_AUTOIMPORT=false + +# +# Is the /autoupload endpoint enabled? +# By default it's disabled, and the secret alone will not enable it. +# +CAN_POST_FILES=false + +# +# Import directory white list. You need to set this before the auto importer will accept a directory to import from. +# +# This variable can be set from a file if you append it with _FILE +# +IMPORT_DIR_ALLOWLIST= + +# +# If you import from a directory, you can save a fallback configuration file in the directory. +# This file must be called "_fallback.json" and will be used when your CSV or CAMT.053 file is not accompanied +# by a configuration file. +# +# This fallback configuration will only be used if this variable is set to true. +# https://docs.firefly-iii.org/how-to/data-importer/advanced/post/#importing-a-local-directory +# +FALLBACK_IN_DIR=false + +# +# When you're running Firefly III under a (self-signed) certificate, +# the data importer may have trouble verifying the TLS connection. +# +# You have a few options to make sure the data importer can connect +# to Firefly III: +# - 'true': will verify all certificates. The most secure option and the default. +# - 'file.pem': refer to a file (you must provide it) to your custom root or intermediate certificates. +# - 'false': will verify NO certificates. Not very secure. +VERIFY_TLS_SECURITY=true + +# +# If you want, you can set a directory here where the data importer will look for import configurations. +# This is a separate setting from the /import directory that the auto-import uses. +# Setting this variable isn't necessary. The default value is "storage/configurations". +# +# This variable can be set from a file if you append it with _FILE +# +JSON_CONFIGURATION_DIR= + +# +# Time out when connecting with Firefly III. +# π*10 seconds is usually fine. +# +CONNECTION_TIMEOUT=31.41 + +# The following variables can be useful when debugging the application +APP_ENV=local +APP_DEBUG=false +LOG_CHANNEL=stack + +# +# If you turn this on, expect massive logs with lots of privacy sensitive data +# +LOG_RETURN_JSON=false + +# Log level. You can set this from least severe to most severe: +# debug, info, notice, warning, error, critical, alert, emergency +# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably +# nothing will get logged, ever. +LOG_LEVEL=info + +# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. +# Set it to ** and reverse proxies work just fine. +TRUSTED_PROXIES=** + +# +# Email settings. +# The data importer can send you a message with all errors, warnings and messages +# after a successful import. This is disabled by default +# +ENABLE_MAIL_REPORT=false + +# +# Force Firefly III URL to be secure? +# +# +EXPECT_SECURE_URL=false + +# If enabled, define which mailer you want to use. +# Options include: smtp, mailgun, postmark, sendmail, log, array +# Amazon SES is not supported. +# log = drop mails in the logs instead of sending them +# array = debug mailer that does nothing. +MAIL_MAILER= + +# where to send the report? +MAIL_DESTINATION=${FFIII_MAIL_DESTINATION_FILE} + +# other mail settings +# These variables can be set from a file if you append it with _FILE +MAIL_FROM_ADDRESS_FILE=${FFIII_MAIL_FROM_FILE} +MAIL_HOST_FILE=${FFIII_MAIL_HOST_FILE} +MAIL_PORT=${FFIII_MAIL_PORT} +MAIL_USERNAME_FILE=${FFIII_MAIL_USERNAME_FILE} +MAIL_PASSWORD_FILE=${FFIII_MAIL_PASSWORD_FILE} +MAIL_ENCRYPTION=null + +# Extra settings depending on your mail configuration above. +# These variables can be set from a file if you append it with _FILE +MAILGUN_DOMAIN= +MAILGUN_SECRET= +MAILGUN_ENDPOINT= +POSTMARK_TOKEN= + +# +# You probably won't need to change these settings. +# +BROADCAST_DRIVER=log +CACHE_DRIVER=file +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 +IS_EXTERNAL=false + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +# always use quotes +REDIS_DB="0" +REDIS_CACHE_DB="1" + +# +# Use ASSET_URL when your data importer webpages are served from a URL with a subfolder path +# This pre-appends the subfolder path in front of URLs for browser-side assets such as CSS Files. +# Example: If your webserver (i.e. NGINX) is configured to serve the data importer webpages from +# http://localhost/ff3di, set ASSET_URL = /ff3di +# and it will pre-append that value to any requests for browser-side assets +# 1) Make sure you REMOVE any trailing slash from the end of the URL. +# +ASSET_URL= + +# The only tracker supported is Matomo. +# This is used on the public instance over at https://data-importer.firefly-iii.org +TRACKER_SITE_ID= +TRACKER_URL= + +APP_NAME=DataImporter + +# +# The APP_URL environment variable is NOT used anywhere. +# Don't bother setting it to fix your reverse proxy problems. It won't help. +# Don't open issues telling me it doesn't help because it's not supposed to. +# Laravel uses this to generate links on the command line, which is a feature the data importer does not use. +# +APP_URL=http://localhost \ No newline at end of file diff --git a/fireflyiii/stacks/.postgresql.env b/fireflyiii/stacks/.postgresql.env new file mode 100644 index 0000000..7f6469b --- /dev/null +++ b/fireflyiii/stacks/.postgresql.env @@ -0,0 +1,8 @@ + +PUID=70 +PGID=70 +TZ=Africa/Johannesburg + +POSTGRES_DB_FILE=${FFIII_DB_NAME_FILE} +POSTGRES_USER_FILE=${FFIII_DB_USER_FILE} +POSTGRES_PASSWORD_FILE=${FFIII_DB_PASSWORD_FILE} diff --git a/fireflyiii/stacks/compose.yml b/fireflyiii/stacks/compose.yml new file mode 100644 index 0000000..8febddf --- /dev/null +++ b/fireflyiii/stacks/compose.yml @@ -0,0 +1,183 @@ +# https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/ +# +# The Firefly III Data Importer will ask you for the Firefly III URL and a "Client ID". +# You can generate the Client ID at http://localhost/profile (after registering) +# The Firefly III URL is: http://app:8080 +# +# Other URL's will give 500 | Server Error +# +name: fireflyiii + +networks: + traefik-net: + external: true + fireflyiii-net: + external: true + +secrets: + fireflyiii_access_token: + file: ${SECRETSDIR}/fireflyiii_access_token + fireflyiii_app_key: + file: ${SECRETSDIR}/fireflyiii_app_key + fireflyiii_default_lat: + file: ${SECRETSDIR}/fireflyiii_default_lat + fireflyiii_default_long: + file: ${SECRETSDIR}/fireflyiii_default_long + fireflyiii_mail_destination: + file: ${SECRETSDIR}/fireflyiii_mail_destination + fireflyiii_mail_from: + file: ${SECRETSDIR}/fireflyiii_mail_from + fireflyiii_mail_host: + file: ${SECRETSDIR}/fireflyiii_mail_host + fireflyiii_mail_password: + file: ${SECRETSDIR}/fireflyiii_mail_password + fireflyiii_mail_username: + file: ${SECRETSDIR}/fireflyiii_mail_username + fireflyiii_postgresql_database: + file: ${SECRETSDIR}/fireflyiii_postgresql_database + fireflyiii_postgresql_password: + file: ${SECRETSDIR}/fireflyiii_postgresql_password + fireflyiii_postgresql_username: + file: ${SECRETSDIR}/fireflyiii_postgresql_username + fireflyiii_site_owner: + file: ${SECRETSDIR}/fireflyiii_site_owner + fireflyiii_static_cron_token: + file: ${SECRETSDIR}/fireflyiii_static_cron_token + +services: + firefly: + image: fireflyiii/core:latest + #image: fireflyiii/core:version-6.1.16 + hostname: "${APPLICATION_NAME}" +# user: ${PUID}:${PGID} + volumes: + - ${DATADIR}/appdata:/var/www/html/storage/upload + - ${DATADIR}/config:/config + restart: unless-stopped + env_file: .firefly.env + networks: + fireflyiii-net: + aliases: ["fireflyiii", "${FFIII_FQDN}"] + traefik-net: {} + depends_on: + postgresql: + condition: service_healthy + secrets: + - fireflyiii_app_key + - fireflyiii_default_lat + - fireflyiii_default_long + - fireflyiii_mail_from + - fireflyiii_mail_host + - fireflyiii_mail_password + - fireflyiii_mail_username + - fireflyiii_postgresql_database + - fireflyiii_postgresql_password + - fireflyiii_postgresql_username + - fireflyiii_site_owner + - fireflyiii_static_cron_token + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http services + # ------------- + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http routers + # ------------ + # limit router to web ":80" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${FFIII_FQDN}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${FFIII_FQDN}`)&& PathPrefix(`/`)" + # set router to be dedicated to secure requests only for the host specified in match criteria + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # apply tls options + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + + importer: + image: fireflyiii/data-importer:latest + hostname: "${IMPORTER_NAME}" + restart: unless-stopped + env_file: .importer.env +# user: ${PUID}:${PGID} + networks: + traefik-net: {} +# ipv4_address: ${FFIII_IMPORTER_IPV4_ADDRESS} +# aliases: ["${FFIII_IMPORTER_FQDN}"] + depends_on: + - firefly + secrets: + - fireflyiii_access_token + - fireflyiii_mail_from + - fireflyiii_mail_host + - fireflyiii_mail_password + - fireflyiii_mail_username + - fireflyiii_mail_destination + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + - "traefik.http.services.${IMPORTER_NAME}-svc.loadbalancer.server.port=${IMPORTER_WEBUI_PORT}" + - "traefik.http.routers.${IMPORTER_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${IMPORTER_NAME}-rtr.rule=Host(`${FFIII_IMPORTER_FQDN}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${IMPORTER_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + - "traefik.http.routers.${IMPORTER_NAME}-rtr.service=${IMPORTER_NAME}-svc" + - "traefik.http.routers.${IMPORTER_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${IMPORTER_NAME}-secure-rtr.rule=Host(`${FFIII_IMPORTER_FQDN}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${IMPORTER_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${IMPORTER_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${IMPORTER_NAME}-secure-rtr.tls.certresolver=solver-dns" + - "traefik.http.routers.${IMPORTER_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${IMPORTER_NAME}-secure-rtr.service=${IMPORTER_NAME}-svc" + + postgresql: + image: postgres:16-alpine + hostname: "firefly_postgresql" + shm_size: 128mb # https://hub.docker.com/_/postgres + restart: unless-stopped + env_file: .postgresql.env + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + networks: + fireflyiii-net: + aliases: ["fireflyiii_postgresql"] + secrets: + - fireflyiii_postgresql_database + - fireflyiii_postgresql_password + - fireflyiii_postgresql_username + volumes: + - "${DATADIR}/pgdata:/var/lib/postgresql/data" + - "${DATADIR}/pgbackups:/mnt/backups" + + cron: + # + # To make this work, set STATIC_CRON_TOKEN in your .env file or as an environment variable + # The STATIC_CRON_TOKEN must be *exactly* 32 characters long + # Generate the token with + # openssl rand 32 | base64 -w 0 | sed 's/[\$,\#,/,+,=]//g' | cut -c -32 + # + image: alpine + restart: always + secrets: + - fireflyiii_static_cron_token + command: sh -c "echo \"0 3 * * * wget -qO- http://fireflyiii:8080/api/v1/cron/$${STATIC_CRON_TOKEN}\" | crontab - && crond -f -L /dev/stdout" + networks: + - fireflyiii-net diff --git a/folders.txt b/folders.txt new file mode 100644 index 0000000..982736b --- /dev/null +++ b/folders.txt @@ -0,0 +1,34 @@ +APPLICATION_NAME= + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media +DOWNLOADSDIR=/mnt/stpool1/Downloads + +STAGINGDIR=/mnt/stpool1/NData1/staging +SHAREDDATADIR=/mnt/stpool1/Shared_Data +BULKSTOREDIR=/mnt/stpool1/NData2/bulkstore +SYNCHEDDIR=/mnt/stpool1/synched +OBJECTSTOREDIR=/mnt/stpool1/objectstore + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + + + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + + + + --bind='/mnt/SSD1/docker/data:/mnt/data' + --bind='/mnt/SSD1/docker/stacks:/opt/stacks' + --bind='/mnt/stpool1/NData1/Media:/mnt/media' + --bind='/mnt/stpool1/NData1/staging:/mnt/staging' + --bind='/mnt/stpool1/NData2/bulkstore:/mnt/bulkstore' + --bind='/mnt/stpool1/Downloads:/mnt/downloads' + --bind='/mnt/stpool1/Shared_Data:/mnt/shared' + --bind='/mnt/stpool1/synched:/mnt/synched' + --bind='/mnt/stpool1/objectstore:/mnt/objectstore' +# --bind='/mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net:/mnt/migrate' \ No newline at end of file diff --git a/gitea/app.ini.rar b/gitea/app.ini.rar new file mode 100644 index 0000000..596b4a8 Binary files /dev/null and b/gitea/app.ini.rar differ diff --git a/gitea/cp2nas.ps1 b/gitea/cp2nas.ps1 new file mode 100644 index 0000000..6778989 --- /dev/null +++ b/gitea/cp2nas.ps1 @@ -0,0 +1,57 @@ +############### MAIN ############### +$Main = +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + [Parameter(Mandatory=$false)] + [string[]] $apps + ) + If($PSBoundParameters.ContainsKey("apps")) { + foreach ($appname in $apps) + { + copyfolder $destHost "$appname\stacks" $appname + } + } + else { + $appname="$pwd".Split("\\")[-1] + copyfolder $destHost "stacks" $appname + } +} + +################################### +Function copyfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $appname + ) + if (-Not(Test-Path -Path $srcdir)) { + Write-Host "Source path doesn't exist: ""$PSScriptRoot\$srcdir\*.*"". No files copied!" -ForegroundColor Red + Write-Host "Usage: in app folder : ./cp2nas DEST|IP" + Write-Host " in app parent folder: ./cp2nas DEST|IP app1, app2, app3, ..." + return + } + $destStacks="/mnt/SSD1/docker/stacks/" + $destDir=$destStacks+$appname+"/" + Write-Host "pscp -P 22 -r ""$srcdir\*.*"" root@${destHost}:""${destDir}""" -ForegroundColor Green + Write-Host "Copying to ${destHost}:""${destStacks}" -NoNewline + Write-Host "${appname}/" -ForegroundColor DarkYellow -NoNewline + Write-Host """:" + pscp -P 22 -r "$srcdir\*.*" root@${destHost}:""${destDir}"" +} + +################################### +& $Main @Args \ No newline at end of file diff --git a/gitea/gitea_jm.txt b/gitea/gitea_jm.txt new file mode 100644 index 0000000..a6f7b7d --- /dev/null +++ b/gitea/gitea_jm.txt @@ -0,0 +1,264 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: git +Username: git +Disable Password: +Email: +UID: 1000 +Create New Primary Group: +Create Home Directory: +Samba Authentication: +Save +Credentials -> Local Groups -> Add +Name: git +GID: 1000 + +PUID: 1000 +PGID: 1000 +Update .env file accordingly (PUID, PGID) + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*gitea" +# create following datasets if not present +zfs create SSD1/docker/data/gitea +zfs create SSD1/docker/data/gitea/appdata +zfs create SSD1/docker/data/gitea/backups +zfs create SSD1/docker/data/gitea/pgdata +zfs create SSD1/docker/data/gitea/pgbackups +chown -R git:git /mnt/SSD1/docker/data/gitea +chown -R postgres:postgres /mnt/SSD1/docker/data/gitea/pgdata +chown -R postgres:postgres /mnt/SSD1/docker/data/gitea/pgbackups + +Create folder +------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/gitea/secrets + +Create secrets +-------------- +In Truenas shell: +cd /mnt/SSD1/docker/stacks/gitea/secrets/ +# database secrets +echo -n 'gitea' > /mnt/SSD1/docker/stacks/gitea/secrets/gitea_postgresql_database +echo -n 'gitea' > /mnt/SSD1/docker/stacks/gitea/secrets/gitea_postgresql_username +openssl rand 36 | base64 -w 0 > /mnt/SSD1/docker/stacks/gitea/secrets/gitea_postgresql_password +# smtp email secrets +echo -n 'your_smtp_destination' > /mnt/SSD1/docker/stacks/gitea/secrets/smtp_destination +echo -n 'your_smtp_from' > /mnt/SSD1/docker/stacks/gitea/secrets/smtp_from +echo -n 'your_smtp_host' > /mnt/SSD1/docker/stacks/gitea/secrets/smtp_host +echo -n 'your_smtp_username' > /mnt/SSD1/docker/stacks/gitea/secrets/smtp_username +echo -n 'your_smtp_password' > /mnt/SSD1/docker/stacks/gitea/secrets/smtp_password +# restrict access +chown -R git:git /mnt/SSD1/docker/stacks/gitea/secrets/ +chmod -R 400 /mnt/SSD1/docker/stacks/gitea/secrets/ +# read existing acl permissions, if any +getfacl /mnt/SSD1/docker/stacks/gitea/secrets +# set acl permissions +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/gitea/secrets +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/gitea/secrets/gitea_postgresql_password +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/gitea/secrets/gitea_postgresql_username +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/gitea/secrets/gitea_postgresql_database +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R +# to list secrets in secrets dir +cd /mnt/SSD1/docker/stacks/gitea/secrets +for i in $(ls -1); do echo $i = `cat $i`; done | sort + +Copy folder to docker stacks +---------------------------- +In Windows cmd shell in gitea parent (apps) folder, enter: +./cp2nas 10.0.0.20 gitea +# or +pscp -P 22 -r gitea/stacks/*.* root@10.0.0.20:/mnt/SSD1/docker/stacks/gitea/ + +Backup gitea database +--------------------- +In truenas shell: +mkdir /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) +chown pgadmin:pgadmin /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) + +Using browser log in to pgAdmin +Connect to servers; refer to "connecting to servers.txt", which also explains how to obtain db passwords +To perform plain text backup: +Navigate to Servers => gitea -> Databases -> gitea +Right click on gitea database and select Backup... +Enter the following on the different tabs of dialog box that opened: +General: +Replace ##### with today's date in YYYY-MM-DD format +Filename: /#####/gitea-backup.sql (this maps to: /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/#####/gitea-backup.sql on truenas) +Format: Plain +Encoding: UTF8 +Role name: gitea +Data Options: +Sections: +Pre-data: +Post-data: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Data: +Objects: +Check public to select all objects +Click Backup +# After backup, verify presence of backup file: +ls -al /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) +# copy backup file(s) to home-assistant backups folder, replacing $(date -I) with date when backup was made if not today +cp -vr /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) /mnt/SSD1/docker/data/home-assistant/pgbackups + +Migrating config storage (not effective) +------------------------ +# Stop home-assistant on truenas, in truenas shell +heavyscript app --stop home-assistant +# copy config storage to new install data folder +cp -pr /mnt/stpool1/apps/home-assistant/* /mnt/SSD1/docker/data/home-assistant/config/ +chown -R hmeassist:hmeassist /mnt/SSD1/docker/data/home-assistant/config/ +# edit configuration.yml to apply values for new app +nano /mnt/SSD1/docker/data/home-assistant/config/configuration.yaml +# under recorder heading, change db_url to reflect the following, replacing with actual password: +db_url: "postgresql://:@home-assistant_postgresql:5432/?client_encoding=utf8" + "postgresql://home-assistant:M1ykv2TSzPD4c7lq4ixyBIl/q9kf4NyVIziQ3Yzansst4kZx@home-assistant_postgresql:5432/home-assistant?client_encoding=utf8" +# change http.trusted_proxies to reflect the traefik network: + trusted_proxies: + - 10.255.224.0/20 + +Migrating database (not effective) +------------------ +# In truenas shell +jlmkr shell docker +cd /opt/stacks/home-assistant +docker compose down +# remove all files/folders from pgdata; if any are already in this folder with data to be retained, move it to another folder before executing next command +rm -r /mnt/data/home-assistant/pgdata/* +docker compose up -d +# After successfull startup of home-assistant and postgres, stop home-assistant from docker cmd line +docker stop home-assistant +docker exec home-assistant_postgresql psql -U -d postgres -c "DROP DATABASE \"\";" +docker exec home-assistant_postgresql psql -U -d postgres -c "CREATE DATABASE \"\";" +docker exec home-assistant_postgresql psql -U -d -f /mnt/backups/$(date -I)/home-assistant-backup.sql # replace $(date -I) with the appropriate date +docker start home-assistant + +Stop truenas home-assistant +--------------------------- +# In truenas shell +heavyscript app --stop home-assistant +# NB: Do NOT stop home-assistant with truenas gui + +Setup MQTT integration +---------------------- +# on home-assistant browser tab +# go to Settings -> Devices & services +# Click on ADD INTEGRATION +# Select MQTT +# Enter mosquitto info as per mosquitto installation + + +# IF DO NOT HAVE FRIGATE RUNNING BY ITSELF, YOU CAN INSTALL WITH HOME-ASSISTANT +Installing HACS +--------------- +docker exec -it home-assistant bash +cd ~ +wget -O - https://get.hacs.xyz | bash - +exit +docker restart home-assistant +# +Setup HACS integration +---------------------- +# https://hacs.xyz/docs/use/configuration/basic/#to-set-up-the-hacs-integration +# after downloading HACS and restarting home-assistant: +# on home-assistant browser tab, press ctrl-F5 +# go to Settings -> Devices & services +# Click on ADD INTEGRATION +# Select HACS +# Acknowledge the statements and select Submit +# Copy the device code and select the link https://github.com/login/device +# if required, sign up or sign in to github to continue the setup +# Enter the device code you copied in the previous step and select Continue +# Select Authorize HACS +# Once you see the confirmation screen, you can close the tab and go back to Home Assistant +# Assign HACS to an area and select Finish. +# +Setup Frigate on home-assistant +------------------------------- +# open home-assistant and select HACS +# type frigate in search text box +# select Frigate Hass Integration +# download and configure + + +If you need to log into db +-------------------------- +docker exec -it home-assistant_postgresql bash +psql -U -d + + diff --git a/home-assistant/stacks/.env b/home-assistant/stacks/.env new file mode 100644 index 0000000..bbe8634 --- /dev/null +++ b/home-assistant/stacks/.env @@ -0,0 +1,25 @@ +# +# values to be used for substitution by docker compose in compose.yml AND .*.env files +# +APPLICATION_NAME=home-assistant +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media +DOWNLOADSDIR=/mnt/stpool1/Downloads + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org +WEBUI_PORT=8123 + +# +# Generate DB_PASSWORD with: +# openssl rand 36 | base64 -w 0 > /mnt/SSD1/docker/stacks/home-assistant/secrets/home-assistant_postgresql_password + +POSTGRES_DB_PORT=5432 +POSTGRES_DB_HOST=home-assistant_postgresql +POSTGRES_DB_NAME=/run/secrets/home-assistant_postgresql_database +POSTGRES_DB_USER=/run/secrets/home-assistant_postgresql_username +POSTGRES_DB_PASSWORD=/run/secrets/home-assistant_postgresql_password diff --git a/home-assistant/stacks/.home-assistant.env b/home-assistant/stacks/.home-assistant.env new file mode 100644 index 0000000..8a721e2 --- /dev/null +++ b/home-assistant/stacks/.home-assistant.env @@ -0,0 +1,12 @@ +# +# environment variables for home-assistant +# +PUID=3035 +PGID=3034 +TZ=Africa/Johannesburg +PORT=${WEBUI_PORT} #8123 + + + + + diff --git a/home-assistant/stacks/.postgresql.env b/home-assistant/stacks/.postgresql.env new file mode 100644 index 0000000..be0e2f1 --- /dev/null +++ b/home-assistant/stacks/.postgresql.env @@ -0,0 +1,9 @@ +PUID=70 +PGID=70 +TZ=Africa/Johannesburg + +DB_HOST=${POSTGRES_DB_HOST} +DB_PORT=${POSTGRES_DB_PORT} +POSTGRES_DB_FILE=${POSTGRES_DB_NAME} +POSTGRES_USER_FILE=${POSTGRES_DB_USER} +POSTGRES_PASSWORD_FILE=${POSTGRES_DB_PASSWORD} diff --git a/home-assistant/stacks/compose.yml b/home-assistant/stacks/compose.yml new file mode 100644 index 0000000..36830f7 --- /dev/null +++ b/home-assistant/stacks/compose.yml @@ -0,0 +1,96 @@ + +name: home-assistant + +secrets: + home-assistant_postgresql_database: + file: ${SECRETSDIR}/home-assistant_postgresql_database + home-assistant_postgresql_password: + file: ${SECRETSDIR}/home-assistant_postgresql_password + home-assistant_postgresql_username: + file: ${SECRETSDIR}/home-assistant_postgresql_username + +networks: + traefik-net: + external: true + postgres-net: + external: true + +services: + home-assistant: + image: "ghcr.io/home-assistant/home-assistant:stable" + hostname: home-assistant + privileged: true + volumes: + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/config:/config" + - /run/dbus:/run/dbus:ro + restart: unless-stopped + env_file: .home-assistant.env + networks: + - traefik-net + - postgres-net + depends_on: + postgresql: + condition: service_healthy + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # http middlewares + # --------------------------- + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.users=${ADMIN_CREDENTIALS}, ${USER_CREDENTIALS}" + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/common.txt" + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.permanent=true" + # + # http services + # ------------- + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http routers + # ------------ + # limit router to web ":80" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=${APPLICATION_NAME}-https-redirect" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # set router to be dedicated to secure requests only for the host specified in match criteria + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=sthomeresolver" + # attach middlewares to router + #- "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + + postgresql: + image: postgres:16-alpine + hostname: "${APPLICATION_NAME}_postgresql" + shm_size: 128mb # https://hub.docker.com/_/postgres + restart: unless-stopped + env_file: .postgresql.env + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + networks: + postgres-net: + aliases: ["home-assistant_postgresql"] + secrets: + - home-assistant_postgresql_database + - home-assistant_postgresql_password + - home-assistant_postgresql_username + volumes: + - "${DATADIR}/pgdata:/var/lib/postgresql/data" + - "${DATADIR}/pgbackups:/mnt/backups" + + diff --git a/jellyfin/jellyfin_jm.txt b/jellyfin/jellyfin_jm.txt new file mode 100644 index 0000000..b7f82fc --- /dev/null +++ b/jellyfin/jellyfin_jm.txt @@ -0,0 +1,65 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: jellyfin +Username: jellyfin +Disable Password: +Email: +UID: (note) +Create New Primary Group: +Email: +UID: (note) +Create New Primary Group: +Email: +UID: (note) +Create New Primary Group: +Email: +UID: (note) +Create New Primary Group: +Data: +Objects: +Check public to select all objects +Click Backup +# After backup, verify presence of backup file: +ls -al /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) +# copy backup file(s) to mealie backups folder, replacing $(date -I) with date when backup was made if not today +mkdir /mnt/SSD1/docker/data/mealie/pgbackups/$(date -I)/ +cp -vr /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I)/mealie-backup.sql /mnt/SSD1/docker/data/mealie/pgbackups/$(date -I)/ +chown -R postgres:postgres /mnt/SSD1/docker/data/mealie/pgbackups/ + +Migrating database +------------------ +# In truenas shell +jlmkr shell docker +cd /opt/stacks/mealie +docker compose down +# remove all files/folders from pgdata; if any are already in this folder with data to be retained, move it to another folder before executing next command +rm -r /mnt/data/mealie/pgdata/* +# for some reason, mealie interferes with the database if it starts up with postgresql the first time, therefore we need to treat mealie a bit differently +# in Windows, comment out the complete mealie service in the compose.yml file (if you use notepad++, left click on start of the first row of the mealie service, hold in ALT and SHIFT and drag mouse down in the same column to the last row of the service; release ALT, SHIFT and mouse button and type in #; then hit ESC) +# transfer the mealie stack with the modified compose.yml file to truenas; in mealie folder, execute: +./cp2nas 10.0.0.20 +# or +pscp -P 22 -r stacks/*.* root@10.0.0.20:/mnt/SSD1/docker/stacks/mealie/ +# start, this time only postgresql will start +docker compose up -d +# After successfull startup of postgres: +docker exec mealie-postgresql-1 psql -U -d postgres -c "DROP DATABASE \"\";" +docker exec mealie-postgresql-1 psql -U -d postgres -c "CREATE DATABASE \"\";" +docker exec mealie-postgresql-1 psql -U -d -f /mnt/backups/$(date -I)/mealie-backup.sql # replace $(date -I) with the appropriate date +# stop postgresql +docker compose down +# now undo the comment out of the mealie service in the compose.yml file (if you use notepad++, you can remove the # using the same steps as described above, except this time, press delete to delete the column of #'s) +# transfer the mealie stack with the restored compose.yml file to truenas; in mealie folder, execute: +./cp2nas 10.0.0.20 +# or +pscp -P 22 -r stacks/*.* root@10.0.0.20:/mnt/SSD1/docker/stacks/mealie/ +# start mealie and postgresql +docker compose up -d + +docker stop mealie-mealie-1 +docker exec mealie-postgresql-1 psql -U mealie -d postgres -c "DROP DATABASE \"mealie\";" +docker exec mealie-postgresql-1 psql -U mealie -d postgres -c "CREATE DATABASE \"mealie\";" +docker exec mealie-postgresql-1 psql -U mealie -d mealie -f /mnt/backups/2024-09-01/mealie-backup.sql +docker start mealie-mealie-1 + +Stop truenas mealie +--------------------------- +# In truenas shell +heavyscript app --stop mealie +# NB: Do NOT stop mealie with truenas gui + +If you need to log into db +-------------------------- +docker exec -it mealie_postgresql bash +psql -U -d + + + + + diff --git a/mealie/stacks/.env b/mealie/stacks/.env new file mode 100644 index 0000000..27d51ef --- /dev/null +++ b/mealie/stacks/.env @@ -0,0 +1,44 @@ + +APPLICATION_NAME=mealie + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +PUID=3011 +PGID=3010 +PG_UID=70 +PG_GID=70 + +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org +WEBUI_PORT=9000 + +MEALIE_DB_PORT=5432 +MEALIE_DB_FILE=/run/secrets/mealie_postgresql_database +MEALIE_DB_USER_FILE=/run/secrets/mealie_postgresql_username +MEALIE_DB_PASSWORD_FILE=/run/secrets/mealie_postgresql_password + +SMTP_PORT=25 +SMTP_SSL=true +SMTP_FROM_FILE=/run/secrets/mealie_smtp_from +SMTP_HOST_FILE=/run/secrets/mealie_smtp_host +SMTP_PASSWORD_FILE=/run/secrets/mealie_smtp_password +SMTP_USERNAME_FILE=/run/secrets/mealie_smtp_username +SMTP_AUTH_STRATEGY=NONE # Options: 'TLS', 'SSL', 'NONE' + +################################################################ +# unfortunately, couldn't get mealie to work with docker secrets +MEALIE_DB=mealie +MEALIE_DB_USER=mealie +MEALIE_DB_PASSWORD="jVaGsWdohfnAVYn7hIxSh94qAzLi6G2BYd9TnaeS" +SMTP_HOST=smtp.telkomsa.net +SMTP_FROM=stuurman30@telkomsa.net +SMTP_USERNAME=stuurman30@telkomsa.net +SMTP_PASSWORD=UltraM3!2024# + + diff --git a/mealie/stacks/.mealie.env b/mealie/stacks/.mealie.env new file mode 100644 index 0000000..e000f5b --- /dev/null +++ b/mealie/stacks/.mealie.env @@ -0,0 +1,42 @@ + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +BASE_URL=https://${APPLICATION_NAME}.${DOMAINNAME} +DOMAIN=https://${APPLICATION_NAME}.${DOMAINNAME} + +SIGNUPS_ALLOWED=false ##change to false once the admin account is created +ALLOW_SIGNUP=false +WEBSOCKET_ENABLED=true +MAX_WORKERS=1 +WEB_CONCURRENCY=1 + +# Database Configuration +DB_ENGINE=postgres +POSTGRES_SERVER=mealie_postgresql +POSTGRES_PORT=${MEALIE_DB_PORT} +# secrets +POSTGRES_DB_FILE=${MEALIE_DB_FILE} +POSTGRES_USER_FILE=${MEALIE_DB_USER_FILE} +POSTGRES_PASSWORD_FILE=${MEALIE_DB_PASSWORD_FILE} + +# Email Configuration +SMTP_PORT=${SMTP_PORT} +SMTP_AUTH_STRATEGY=${SMTP_AUTH_STRATEGY} +# secrets +SMTP_FROM_FILE=${SMTP_FROM_FILE} +SMTP_HOST_FILE=${SMTP_HOST_FILE} +SMTP_PASSWORD_FILE=${SMTP_PASSWORD_FILE} +SMTP_USERNAME_FILE=${SMTP_USERNAME_FILE} + +################################################################################ +# unfortunately, couldn't get mealie to work with docker secrets, so we need to override above with clear text "secrets" +POSTGRES_DB=${MEALIE_DB} +POSTGRES_USER=${MEALIE_DB_USER} +POSTGRES_PASSWORD=${MEALIE_DB_PASSWORD} +SMTP_FROM=${SMTP_FROM} +SMTP_HOST=${SMTP_HOST} +SMTP_PASSWORD=${SMTP_PASSWORD} +SMTP_USERNAME=${SMTP_USERNAME} + diff --git a/mealie/stacks/.postgresql.env b/mealie/stacks/.postgresql.env new file mode 100644 index 0000000..4c548df --- /dev/null +++ b/mealie/stacks/.postgresql.env @@ -0,0 +1,10 @@ + +PUID=70 +PGID=70 +TZ=Africa/Johannesburg + +POSTGRES_DB_PORT=${MEALIE_DB_PORT} +POSTGRES_DB_FILE=${MEALIE_DB_FILE} +POSTGRES_USER_FILE=${MEALIE_DB_USER_FILE} +POSTGRES_PASSWORD_FILE=${MEALIE_DB_PASSWORD_FILE} + diff --git a/mealie/stacks/compose.yml b/mealie/stacks/compose.yml new file mode 100644 index 0000000..f0ab4ca --- /dev/null +++ b/mealie/stacks/compose.yml @@ -0,0 +1,97 @@ +# https://github.com/mealie-recipes/mealie/pkgs/container/mealie +# https://docs.mealie.io/documentation/getting-started/installation/postgres/ + +name: mealie + +secrets: + mealie_postgresql_password: + file: ${SECRETSDIR}/mealie_postgresql_password + mealie_postgresql_database: + file: ${SECRETSDIR}/mealie_postgresql_database + mealie_postgresql_username: + file: ${SECRETSDIR}/mealie_postgresql_username + smtp_destination: + file: ${SECRETSDIR}/smtp_destination + smtp_from: + file: ${SECRETSDIR}/smtp_from + smtp_host: + file: ${SECRETSDIR}/smtp_host + smtp_password: + file: ${SECRETSDIR}/smtp_password + smtp_username: + file: ${SECRETSDIR}/smtp_username + +networks: + traefik-net: + external: true + postgres-net: + external: true + +services: + mealie: + image: ghcr.io/mealie-recipes/mealie:v2.2.0 # v1.12.0 + hostname: mealie + env_file: .mealie.env + restart: unless-stopped + deploy: + resources: + limits: + memory: 1000M + volumes: + - "${DATADIR}/appdata:/app/data" + depends_on: + postgresql: + condition: service_healthy + secrets: + - mealie_postgresql_database + - mealie_postgresql_password + - mealie_postgresql_username + - smtp_destination + - smtp_from + - smtp_host + - smtp_password + - smtp_username + networks: + - postgres-net + - traefik-net + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + + postgresql: + image: postgres:16-alpine + hostname: "mealie_postgresql" + shm_size: 128mb + restart: unless-stopped + env_file: .postgresql.env + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + networks: + postgres-net: + aliases: ["mealie_postgresql"] + secrets: + - mealie_postgresql_database + - mealie_postgresql_password + - mealie_postgresql_username + volumes: + - "${DATADIR}/pgdata:/var/lib/postgresql/data" + - "${DATADIR}/pgbackups:/mnt/backups" diff --git a/mediaelch/mediaelch_jm.txt b/mediaelch/mediaelch_jm.txt new file mode 100644 index 0000000..dfde70a --- /dev/null +++ b/mediaelch/mediaelch_jm.txt @@ -0,0 +1,64 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: mediaelch +Username: mediaelc +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +mediaelc UID: 3042 +mediaelc GID: 3017 #3041 + +If not done already, add mapping for media on container config +-------------------------------------------------------------- +In this example: the folder where media is stored is /mnt/stpool1/NData1/Media +On Truenas shell: +jlmkr edit docker +Add the following args to "systemd_nspawn_user_args": +--bind='/mnt/stpool1/NData1/Media:/mnt/media' + +If not done already, set ACL permissions for media to be accessible by media group +---------------------------------------------------------------------------------- +On Truenas shell: +# read and note acl entries +getfacl /mnt/stpool1/NData1 +getfacl /mnt/stpool1/NData1/Media +# set read and execute permissions for media group on parent folder +setfacl -m g:media:5 /mnt/stpool1/NData1 +# set full permissions for media group on Media folder recursively +setfacl -R -m g:media:7 /mnt/stpool1/NData1/Media +# modify defaults recursively +setfacl -R -d -m g:media:7 /mnt/stpool1/NData1/Media +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*mediaelch" +# create following datasets if not present +zfs create SSD1/docker/data/mediaelch +zfs create SSD1/docker/data/mediaelch/config +chown -R mediaelc:mediaelc /mnt/SSD1/docker/data/mediaelch + +Create folder +------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/mediaelch + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in mediaelch folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/mediaelch/ +# This should copy mediaelch stacks folder to /mnt/SSD1/docker/stacks/mediaelch + + + + diff --git a/mediaelch/stacks/.env b/mediaelch/stacks/.env new file mode 100644 index 0000000..a4f0d21 --- /dev/null +++ b/mediaelch/stacks/.env @@ -0,0 +1,23 @@ + +APPLICATION_NAME=mediaelch + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +CT_DOWNLOADS=/Downloads +CT_MEDIA=/Media +MEDIA_GID=3017 +PUID=3042 +PGID=3041 +DOMAINNAME=sthome.org + +WEBUI_PORT=3000 +SECURE_WEBUI_PORT=3001 + + + diff --git a/mediaelch/stacks/.mediaelch.env b/mediaelch/stacks/.mediaelch.env new file mode 100644 index 0000000..29d699c --- /dev/null +++ b/mediaelch/stacks/.mediaelch.env @@ -0,0 +1,4 @@ + +PUID=${PUID} +PGID=${MEDIA_GID} +TZ=Africa/Johannesburg diff --git a/mediaelch/stacks/compose.yml b/mediaelch/stacks/compose.yml new file mode 100644 index 0000000..854b2cd --- /dev/null +++ b/mediaelch/stacks/compose.yml @@ -0,0 +1,60 @@ + +name: mediaelch + +networks: + traefik-net: + external: true + +services: + mediaelch: + image: lscr.io/linuxserver/mediaelch:latest + env_file: .mediaelch.env + #user: "${PUID}:${PGID}" + group_add: + - "${MEDIA_GID}" # not really needed if we have it as the primary gid + security_opt: + - seccomp:unconfined #optional + networks: + - traefik-net + volumes: + - "${DATADIR}/config:/config" + - "${MEDIADIR}:${CT_MEDIA}" + restart: unless-stopped + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # http middlewares + # --------------------------- + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.users=${ADMIN_CREDENTIALS}, ${USER_CREDENTIALS}" + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/${APPLICATION_NAME}.txt" + # + # http services + # ------------- + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http routers + # ------------ + # limit router to web ":80" entrypoint (Note: web entrypoint http requests are globally redirected to websecure router in traefik.yml) + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # assign middlewares + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # set router to be dedicated to secure requests only for the host specified in match criteria + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # apply tls options + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # attach middlewares to routers + #- "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" diff --git a/minecraft/mcrcon/LICENSE.txt b/minecraft/mcrcon/LICENSE.txt new file mode 100644 index 0000000..ed733cd --- /dev/null +++ b/minecraft/mcrcon/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2012-2021, Tiiffi + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + diff --git a/minecraft/mcrcon/README.txt b/minecraft/mcrcon/README.txt new file mode 100644 index 0000000..de95daf --- /dev/null +++ b/minecraft/mcrcon/README.txt @@ -0,0 +1,79 @@ +Name: mcrcon (minecraft rcon) +Version: 0.7.2 +Date: 31.10.2021 + +Description: + mcrcon is console based Minecraft rcon client for remote administration and server maintenance scripts. + +License: + zlib/libpng License + +Contact: + WWW: https://github.com/Tiiffi/mcrcon/ + MAIL: tiiffi+mcrcon at gmail + +=================================================================================== + +Batch (.bat) scripts included in Windows binary package: + + launch.bat: + Prompts user for server information and starts "mcrcon.exe" in terminal mode. + + create_shortcut.bat: + Prompts user for server infromation and creates .bat launch script. + +=================================================================================== + +Usage: + mcrcon [OPTIONS] [COMMANDS] + + Send rcon commands to Minecraft server. + + Options: + -H Server address (default: localhost) + -P Port (default: 25575) + -p Rcon password + -t Terminal mode + -s Silent mode + -c Disable colors + -r Output raw packets + -w Wait for specified duration (seconds) between each command (1 - 600s) + -h Print usage + -v Version information + + Server address, port and password can be set with following environment variables: + MCRCON_HOST + MCRCON_PORT + MCRCON_PASS + + - mcrcon will start in terminal mode if no commands are given + - Command-line options will override environment variables + - Rcon commands with spaces must be enclosed in quotes + + Example: + mcrcon -H my.minecraft.server -p password -w 5 "say Server is restarting!" save-all stop + +=================================================================================== + +Changelog: + + 0.7.2 + - Quit gracefully when Ctrl-D or Ctrl+C is pressed + - Remove "exit" and "quit" as quitting commands + * these are actual rcon commands on some servers + - Suppress compiler warning (strncpy) + - fix erroneous string length in packet building function + - Fix typo in ANSI escape sequence for LCYAN + - Make stdout and stderr unbuffered + + 0.7.1 + - Deprecate `-i` flag for invoking terminal mode + - Add workaround to prevent server-side bug. + * https://bugs.mojang.com/browse/MC-154617 + + 0.7.0 + - Add `-w` option for rcon command throttling + * Thanks HorlogeSkynet @ Github + + For more details: https://github.com/Tiiffi/mcrcon/blob/master/CHANGELOG.md + diff --git a/minecraft/mcrcon/create_shortcut.bat b/minecraft/mcrcon/create_shortcut.bat new file mode 100644 index 0000000..bc65353 --- /dev/null +++ b/minecraft/mcrcon/create_shortcut.bat @@ -0,0 +1,31 @@ +@echo off +@cls + +@set /p host="Enter host (default: "127.0.0.1"): " +@if "%host%"=="" set host=127.0.0.1 + +@set /p port="Enter port (default: 25575): " +@if "%port%"=="" set port=25575 + +@set /p passwd="Enter password: " +@if "%passwd%"=="" set passwd= + +set name=connect_%host%-%port% + +@set /p name="Enter shortcut name (default: "%name%.bat"): " +@if "%name%"=="" set name=connect_%host%-%port% + +set command=@mcrcon.exe -t -H %host% -P %port% -p %passwd% + +@echo %command% >> %name%.bat +@echo. +@echo Command: "%command%" +@echo. +@echo Shortcut "%name%.bat" created! +@echo. + +@set "host=" +@set "port=" +@set "passwd=" + +@pause diff --git a/minecraft/mcrcon/launch.bat b/minecraft/mcrcon/launch.bat new file mode 100644 index 0000000..b88abb4 --- /dev/null +++ b/minecraft/mcrcon/launch.bat @@ -0,0 +1,29 @@ +@echo off +@cls + +@if not exist mcrcon.exe ( + @echo ERROR: Cannot find "mcrcon.exe". Bailing out! + @echo. + @pause + @exit +) + +@set /p host="Enter host (default: 127.0.0.1): " +@if "%host%"=="" set host=127.0.0.1 + +@set /p port="Enter port (default: 25575): " +@if "%port%"=="" set port=25575 + +@set /p passwd="Enter password: " +@if "%passwd%"=="" set passwd= + +@echo. +mcrcon.exe -t -H %host% -P %port% -p %passwd% +@echo. + +@set "host=" +@set "port=" +@set "passwd=" + +@pause + diff --git a/minecraft/mcrcon/mcrcon-0.7.2-windows-x86-64.zip b/minecraft/mcrcon/mcrcon-0.7.2-windows-x86-64.zip new file mode 100644 index 0000000..b4ce91c Binary files /dev/null and b/minecraft/mcrcon/mcrcon-0.7.2-windows-x86-64.zip differ diff --git a/minecraft/mcrcon/mcrcon.exe b/minecraft/mcrcon/mcrcon.exe new file mode 100644 index 0000000..b80160a Binary files /dev/null and b/minecraft/mcrcon/mcrcon.exe differ diff --git a/minecraft/minecraft_jm.txt b/minecraft/minecraft_jm.txt new file mode 100644 index 0000000..e04ee11 --- /dev/null +++ b/minecraft/minecraft_jm.txt @@ -0,0 +1,61 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: minecraft +Username: minecraft +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +minecraft UID: 3043 +minecraft GID: 3042 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*minecraft" +# create following datasets if not present +zfs create SSD1/docker/data/minecraft +zfs create SSD1/docker/data/minecraft/bedrock +zfs create SSD1/docker/data/minecraft/java +chown -R minecraft:minecraft /mnt/SSD1/docker/data/minecraft + +Create folders +-------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/minecraft/secrets + +Create secrets +-------------- +# In Truenas shell: +cd /mnt/SSD1/docker/stacks/minecraft/secrets +echo -n 'your_mcjava_rcon_password' > /mnt/SSD1/docker/stacks/minecraft/secrets/mcjava_rcon_password +chown -R minecraft:minecraft /mnt/SSD1/docker/stacks/minecraft/secrets +chmod -R 400 /mnt/SSD1/docker/stacks/minecraft/secrets +# NB! rcon is disabled in env_file. To enable rcon, uncomment ENABLE_RCON in compose.yml environment settings for minecraft-java + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in minecraft folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/minecraft/ +# This should copy minecraft stacks folder to /mnt/SSD1/docker/stacks/minecraft + +Migrating data from old minecraft-bedrock server (source) to newly installed one (target) +----------------------------------------------------------------------------------------- +# Stop old/source minecraft-bedrock server +# heavyscript app --stop minecraft-bedrock +# Stop new/target minecraft-bedrock server +# On Dockge, select minecraft-bedrock and click stop +cp -pr /mnt/stpool1/apps/minecraft/bedrock/* /mnt/SSD1/docker/data/minecraft/bedrock/ +cp -pr /mnt/stpool1/apps/minecraft/java/* /mnt/SSD1/docker/data/minecraft/java/ +chown -R minecraft:minecraft /mnt/SSD1/docker/data/minecraft + + + diff --git a/minecraft/stacks/.env b/minecraft/stacks/.env new file mode 100644 index 0000000..d36f9a1 --- /dev/null +++ b/minecraft/stacks/.env @@ -0,0 +1,37 @@ +############################################################################################## +# Values to be used for substitution by docker compose in compose.yml AND .*.env files +############################################################################################## + +APPLICATION_NAME=minecraft + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org + +SERVICE_PORT=80 +PUID=3043 +PGID=3042 +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org + +# MINECRAFT EDITIONS +# ------------------ +# ensure that traefik has the entry points below + +# Minecraft Bedrock +MCBEDROCK_APP=minecraft-bedrock +MCBEDROCK_PORT=19132 # udp + +# Minecraft Java +MCJAVA_APP=minecraft-java +MCJAVA_PORT=25565 # udp +# +MCJAVA_RCON_PORT=25575 +MCJAVA_RCON_PASSWORD_FILE=/run/secrets/mcjava_rcon_password + diff --git a/minecraft/stacks/.minecraft-bedrock.env b/minecraft/stacks/.minecraft-bedrock.env new file mode 100644 index 0000000..d88c183 --- /dev/null +++ b/minecraft/stacks/.minecraft-bedrock.env @@ -0,0 +1,78 @@ +# https://github.com/itzg/docker-minecraft-bedrock-server?tab=readme-ov-file +# https://minecraft.wiki/w/Server.properties#Option_keys +############################################################################################## +# Environment variables for minecraft-bedrock servers +############################################################################################## + +# Ensure that UID/GID is the owner/group of bedrock folder otherwise container startup will fail with permission error. "bedrock" folder is mapped to container /data +UID=${PUID} +GID=${PGID} +UMASK=0022 +TZ={TZ} + +EULA=TRUE +VERSION=LATEST # LATEST, PREVIEW or specific version +PACKAGE_BACKUP_KEEP=2 + +# Server Properties +# ----------------- +ONLINE_MODE=true +GAMEMODE=survival # survival, creative, adventure, spectator +DIFFICULTY=easy # easy, normal, hard +SERVER_NAME="Dedicated Server on Truenas Scale" +# FORCE_GAMEMODE= +ALLOW_CHEATS=false +MAX_PLAYERS=10 +# WHITE_LIST= +# ALLOW_LIST= +# SERVER_PORT= +# SERVER_PORT_V6= +# ENABLE_LAN_VISIBILITY= +VIEW_DISTANCE=32 +TICK_DISTANCE=4 +PLAYER_IDLE_TIMEOUT=30 +MAX_THREADS=8 +LEVEL_NAME="Bedrock level" +# LEVEL_SEED= +# LEVEL_TYPE=Default +DEFAULT_PLAYER_PERMISSION_LEVEL=member +# TEXTUREPACK_REQUIRED= +# CONTENT_LOG_FILE_ENABLED= +# CONTENT_LOG_LEVEL= +# CONTENT_LOG_CONSOLE_OUTPUT_ENABLED= +# COMPRESSION_THRESHOLD= +# COMPRESSION_ALGORITHM= +SERVER_AUTHORITATIVE_MOVEMENT=server-auth +# PLAYER_POSITION_ACCEPTANCE_THRESHOLD= +PLAYER_MOVEMENT_SCORE_THRESHOLD=20 +# PLAYER_MOVEMENT_ACTION_DIRECTION_THRESHOLD= +PLAYER_MOVEMENT_DISTANCE_THRESHOLD=0.3 +PLAYER_MOVEMENT_DURATION_THRESHOLD_IN_MS=500 +# CORRECT_PLAYER_MOVEMENT= +# SERVER_AUTHORITATIVE_BLOCK_BREAKING= +# SERVER_AUTHORITATIVE_BLOCK_BREAKING_PICK_RANGE_SCALAR= +# CHAT_RESTRICTION= +# DISABLE_PLAYER_INTERACTION= +# CLIENT_SIDE_CHUNK_GENERATION_ENABLED= +# BLOCK_NETWORK_IDS_ARE_HASHES= +# DISABLE_PERSONA= +# DISABLE_CUSTOM_SKINS= +# SERVER_BUILD_RADIUS_RATIO= +# ALLOW_OUTBOUND_SCRIPT_DEBUGGING= +# ALLOW_INBOUND_SCRIPT_DEBUGGING= +# FORCE_INBOUND_DEBUG_PORT= +# SCRIPT_DEBUGGER_AUTO_ATTACH= +# SCRIPT_DEBUGGER_AUTO_ATTACH_CONNECT_ADDRESS= +# SCRIPT_WATCHDOG_ENABLE= +# SCRIPT_WATCHDOG_ENABLE_EXCEPTION_HANDLING= +# SCRIPT_WATCHDOG_ENABLE_SHUTDOWN= +# SCRIPT_WATCHDOG_HANG_EXCEPTION= +# SCRIPT_WATCHDOG_HANG_THRESHOLD= +# SCRIPT_WATCHDOG_SPIKE_THRESHOLD= +# SCRIPT_WATCHDOG_SLOW_THRESHOLD= +# SCRIPT_WATCHDOG_MEMORY_WARNING= +# SCRIPT_WATCHDOG_MEMORY_LIMIT= +# OP_PERMISSION_LEVEL= +# EMIT_SERVER_TELEMETRY= +# MSA_GAMERTAGS_ONLY= +# ITEM_TRANSACTION_LOGGING_ENABLED= diff --git a/minecraft/stacks/.minecraft-java.env b/minecraft/stacks/.minecraft-java.env new file mode 100644 index 0000000..064a53e --- /dev/null +++ b/minecraft/stacks/.minecraft-java.env @@ -0,0 +1,65 @@ +############################################################################################## +# Environment variables for minecraft-java servers +############################################################################################## + +UID=${PUID} +GID=${PGID} +UMASK=0022 +TZ=${TZ} + +EULA=TRUE +VERSION=LATEST +PREVIEW=FALSE +QUERY_PORT=${MCJAVA_PORT} +SERVER_PORT=${MCJAVA_PORT} +# we are not exposing rcon port externally, i.e. no port forwarding on rcon port configured on router +RCON_PASSWORD_FILE=${MCJAVA_RCON_PASSWORD_FILE} +RCON_PORT=${MCJAVA_RCON_PORT} +ENABLE_RCON=false + +# Server Properties +# ----------------- +ONLINE_MODE=true +MODE=survival # survival, creative, adventure, spectator +DIFFICULTY=easy # easy, normal, hard +TYPE=VANILLA # VANILLA, FORGE, NEOFORGE, FABRIC, SPIGOT, BUKKIT +ALLOW_NETHER=true +ANNOUNCE_PLAYER_ACHIEVEMENTS=true +ENABLE_COMMAND_BLOCK=false +FORCE_GAMEMODE=false +FORCE_REDOWNLOAD=false +GENERATE_STRUCTURES=true +GENERATOR_SETTINGS= +HARDCORE=false +LEVEL=world +LEVEL_TYPE=DEFAULT +MAX_BUILD_HEIGHT=256 +MAX_PLAYERS=20 +MAX_TICK_TIME=60000 +MAX_WORLD_SIZE=10000 +MEMORY=2048M +MOTD="Welcome to Minecraft on TrueNAS Scale!" +OPS= +PVP=false +SEED= +SPAWN_ANIMALS=true +SPAWN_MONSTERS=true +SPAWN_NPCS=true +USE_AIKAR_FLAGS=true +USE_FLARE_FLAGS=false +USE_SIMD_FLAGS=false +VIEW_DISTANCE=10 +WHITELIST= +WORLD= + + + + + + + + + + + + diff --git a/minecraft/stacks/compose.yml b/minecraft/stacks/compose.yml new file mode 100644 index 0000000..75502c9 --- /dev/null +++ b/minecraft/stacks/compose.yml @@ -0,0 +1,72 @@ +# NB! since udp routing cannot be made on hostnames, minecraft will have to be accessed as follows: +# minecraft-bedrock: minecraft.sthome.org:19132 +# minecraft-java: minecraft.sthome.org:25565 + +name: minecraft + +secrets: + mcjava_rcon_password: + file: ${SECRETSDIR}/mcjava_rcon_password + +networks: + traefik-net: + external: true + +services: + minecraft-bedrock: + image: itzg/minecraft-bedrock-server + hostname: ${MCBEDROCK_APP} + env_file: .minecraft-bedrock.env + tty: true + stdin_open: true + networks: + - traefik-net + volumes: + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/bedrock:/data" + restart: unless-stopped + # environment variables specified here overrides env_file + environment: + - GAMEMODE=survival + - DIFFICULTY=peaceful + #- DIFFICULTY=easy + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + - "traefik.udp.services.${MCBEDROCK_APP}-svc.loadbalancer.server.port=${MCBEDROCK_PORT}" + - "traefik.udp.routers.${MCBEDROCK_APP}-rtr.entrypoints=mc-bedrock" + - "traefik.udp.routers.${MCBEDROCK_APP}-rtr.service=${MCBEDROCK_APP}-svc" + + minecraft-java: + image: itzg/minecraft-server + hostname: ${MCJAVA_APP} + env_file: .minecraft-java.env + tty: true + stdin_open: true + networks: + - traefik-net + volumes: + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/java:/data" + restart: unless-stopped + secrets: + - mcjava_rcon_password + # environment variables specified here override env_file + environment: + - SERVER_NAME=mc-java + - MODE=survival + - DIFFICULTY=easy + # - ENABLE_RCON=true # uncomment to enable RCON + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # udp entrypoint routed to service port + - "traefik.udp.services.${MCJAVA_APP}-svc.loadbalancer.server.port=${MCJAVA_PORT}" + - "traefik.udp.routers.${MCJAVA_APP}-rtr.entrypoints=mc-java" + - "traefik.udp.routers.${MCJAVA_APP}-rtr.service=${MCJAVA_APP}-svc" + + # tcp entrypoint routed to rcon port - unencrypted (unsafe, do not port forward router) + - "traefik.tcp.services.${MCJAVA_APP}-rcon-svc.loadbalancer.server.port=${MCJAVA_RCON_PORT}" + - "traefik.tcp.routers.${MCJAVA_APP}-rcon-rtr.rule=HostSNI(`*`)" # no matching possible without tls + - "traefik.tcp.routers.${MCJAVA_APP}-rcon-rtr.entrypoints=mc-java-rcon" + - "traefik.tcp.routers.${MCJAVA_APP}-rcon-rtr.service=${MCJAVA_APP}-rcon-svc" diff --git a/minio/minio_jm.txt b/minio/minio_jm.txt new file mode 100644 index 0000000..b62e936 --- /dev/null +++ b/minio/minio_jm.txt @@ -0,0 +1,55 @@ +# https://github.com/jlesage/docker-minio?tab=readme-ov-file + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: minio +Username: minio +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +minio UID: 3045 +minio GID: 3044 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*minio" +# create following datasets if not present +zfs create SSD1/docker/data/minio +zfs create SSD1/docker/data/minio/config +chown -R minio:minio /mnt/SSD1/docker/data/minio + +Create folders +-------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/minio/secrets +mkdir /mnt/stpool1/objectstore/minio/data1-1 +mkdir /mnt/stpool1/objectstore/minio/data1-2 +mkdir /mnt/stpool1/objectstore/minio/data2-1 +mkdir /mnt/stpool1/objectstore/minio/data2-2 +chown -R minio:minio /mnt/stpool1/objectstore/minio + +Create secrets +-------------- +cd /mnt/SSD1/docker/stacks/minio/secrets +echo -n 'your_minio_root_user' > minio_root_user +echo -n 'your_minio_root_password' > minio_root_password +chown -R minio:minio /mnt/SSD1/docker/stacks/minio/secrets +chmod -R 400 /mnt/SSD1/docker/stacks/minio/secrets + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in minio folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/minio/ +# This should copy minio stacks folder to /mnt/SSD1/docker/stacks/minio + + diff --git a/minio/stacks/.env b/minio/stacks/.env new file mode 100644 index 0000000..eebee5c --- /dev/null +++ b/minio/stacks/.env @@ -0,0 +1,19 @@ +APPLICATION_NAME=minio + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media + +OBJECTSTOREDIR=/mnt/stpool1/objectstore + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +TZ=Africa/Johannesburg + +DOMAINNAME=sthome.org +API_PORT=9000 +WEBUI_PORT=9001 +PUID=3045 +PGID=3044 diff --git a/minio/stacks/.minio.env b/minio/stacks/.minio.env new file mode 100644 index 0000000..ae1af57 --- /dev/null +++ b/minio/stacks/.minio.env @@ -0,0 +1,13 @@ + +USER_ID=${PUID} +GROUP_ID=${PGID} +PUID=${PUID} +PGID=${PGID} +UMASK=0022 +TZ=${TZ} +DARK_MODE=1 + +MINIO_ROOT_USER_FILE=/run/secrets/minio_root_user +MINIO_ROOT_PASSWORD_FILE=/run/secrets/minio_root_password + + diff --git a/minio/stacks/compose.yml b/minio/stacks/compose.yml new file mode 100644 index 0000000..815fcb8 --- /dev/null +++ b/minio/stacks/compose.yml @@ -0,0 +1,75 @@ +# https://quay.io/repository/minio/minio?tab=tags + +name: minio + +secrets: + minio_root_user: + file: ${SECRETSDIR}/minio_root_user + minio_root_password: + file: ${SECRETSDIR}/minio_root_password + +networks: + traefik-net: + external: true + +x-minio-common: &minio-common + image: quay.io/minio/minio:RELEASE.2024-09-22T00-33-43Z + user: ${PUID}:${PGID} + command: server --console-address ":9001" http://minio{1...2}/data{1...2} + env_file: .minio.env + secrets: + - minio_root_user + - minio_root_password + restart: unless-stopped + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 5s + retries: 5 + +services: + minio1: + <<: *minio-common + hostname: minio1 + networks: + - traefik-net + volumes: + - "${OBJECTSTOREDIR}/minio/data1-1:/data1" + - "${OBJECTSTOREDIR}/minio/data1-2:/data2" + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + - "traefik.http.services.minio1-svc.loadbalancer.server.port=${WEBUI_PORT}" + - "traefik.http.middlewares.minio1-https-redirect.redirectscheme.scheme=https" + - "traefik.http.routers.minio1-rtr.entrypoints=web" + - "traefik.http.routers.minio1-rtr.rule=Host(`minio1.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.minio1-rtr.middlewares=minio1-https-redirect" + - "traefik.http.routers.minio1-rtr.service=minio1-svc" + - "traefik.http.routers.minio1-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.minio1-secure-rtr.rule=Host(`minio1.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.minio1-secure-rtr.tls=true" + - "traefik.http.routers.minio1-secure-rtr.tls.certresolver=sthomeresolver" + - "traefik.http.routers.minio1-secure-rtr.service=minio1-svc" + + minio2: + <<: *minio-common + hostname: minio2 + networks: + - traefik-net + volumes: + - "${OBJECTSTOREDIR}/minio/data2-1:/data1" + - "${OBJECTSTOREDIR}/minio/data2-2:/data2" + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + - "traefik.http.services.minio2-svc.loadbalancer.server.port=${WEBUI_PORT}" + - "traefik.http.middlewares.minio2-https-redirect.redirectscheme.scheme=https" + - "traefik.http.routers.minio2-rtr.entrypoints=web" + - "traefik.http.routers.minio2-rtr.rule=Host(`minio2.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.minio2-rtr.middlewares=minio2-https-redirect" + - "traefik.http.routers.minio2-rtr.service=minio2-svc" + - "traefik.http.routers.minio2-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.minio2-secure-rtr.rule=Host(`minio2.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.minio2-secure-rtr.tls=true" + - "traefik.http.routers.minio2-secure-rtr.tls.certresolver=sthomeresolver" + - "traefik.http.routers.minio2-secure-rtr.service=minio2-svc" diff --git a/mkvtoolnix/mkvtoolnix_jm.txt b/mkvtoolnix/mkvtoolnix_jm.txt new file mode 100644 index 0000000..ccf2e93 --- /dev/null +++ b/mkvtoolnix/mkvtoolnix_jm.txt @@ -0,0 +1,49 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: mkvtoolnix +Username: mkvtlnix +Disable Password: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Primary Group: mosquitt +Create Home Directory: +Samba Authentication: +Save + +mosquitt UID: 3047 +mosquitt GID: 3046 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*mosquitto" +# create following datasets if not present +zfs create SSD1/docker/data/mosquitto +zfs create SSD1/docker/data/mosquitto/appdata +zfs create SSD1/docker/data/mosquitto/config +zfs create SSD1/docker/data/mosquitto/logs +# create the following dataset if you want the default folder for password.txt to be mapped outside the container +zfs create SSD1/docker/data/mosquitto/configinc +chown -R mosquitt:mosquitt /mnt/SSD1/docker/data/mosquitto + +Create folder +------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/mosquitto + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in mosquitto folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/mosquitto/ +# This should copy mosquitto stacks folder to /mnt/SSD1/docker/stacks/mosquitto + +Migrating data +-------------- +# example mosquitto.conf: +# https://github.com/eclipse/mosquitto/blob/master/mosquitto.conf +# since config file was not persisted outside container, we will have to copy it from the container +# get fullname of pod: +k3s kubectl get pods -n ix-mosquitto +# select and copy the pod name to clipboard to use it in copy command hereafter +# copy the the config file from the container +k3s kubectl cp -c mosquitto ix-mosquitto/:/mosquitto/config/mosquitto.conf /mnt/SSD1/docker/data/mosquitto/config/config/mosquitto.conf +# now for the rest of the files: +# Stop mosquitto on truenas, in truenas shell +heavyscript app --stop mosquitto +cp -pr /mnt/stpool1/appdata/mosquitto/* /mnt/SSD1/docker/data/mosquitto/config/data +# if you have mapped the default folder for password.txt to be outside the container +cp -pr /mnt/stpool1/apps/mosquitto/* /mnt/SSD1/docker/data/mosquitto/config/configinc +chown -R mosquitt:mosquitt /mnt/SSD1/docker/data/mosquitto/ +chmod -R 700 /mnt/SSD1/docker/data/mosquitto/ + +Test mosquitto +-------------- +# TODO + +Setting up certbot to renew certificate +--------------------------------------- +# TODO + + + + diff --git a/mosquitto/stacks/.env b/mosquitto/stacks/.env new file mode 100644 index 0000000..0c34951 --- /dev/null +++ b/mosquitto/stacks/.env @@ -0,0 +1,18 @@ + +APPLICATION_NAME=mosquitto + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media +DOWNLOADSDIR=/mnt/stpool1/Downloads + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org +SERVICE_PORT=1883 +SECURE_SERVICE_PORT=8883 + +PUID=3047 +PGID=3046 diff --git a/mosquitto/stacks/.mosquitto.env b/mosquitto/stacks/.mosquitto.env new file mode 100644 index 0000000..a463818 --- /dev/null +++ b/mosquitto/stacks/.mosquitto.env @@ -0,0 +1,6 @@ + +PUID=${PUID} +PGID=${PGID} +TZ=Africa/Johannesburg + + diff --git a/mosquitto/stacks/compose.yml b/mosquitto/stacks/compose.yml new file mode 100644 index 0000000..f9dd0d6 --- /dev/null +++ b/mosquitto/stacks/compose.yml @@ -0,0 +1,53 @@ +name: mosquitto + +networks: + traefik-net: + external: true + +services: + mosquitto: + image: eclipse-mosquitto + hostname: mosquitto + env_file: .mosquitto.env + user: "${PUID}:${PGID}" + networks: + traefik-net: + aliases: ["mqtt"] + volumes: + - "${DATADIR}/appdata:/mosquitto/data" + - "${DATADIR}/config:/mosquitto/config" + - "${DATADIR}/logs:/mosquitto/log" + - "${DATADIR}/configinc:/mosquitto/configinc" # maps the default folder for password.txt file + restart: unless-stopped + # ports 1883, 8883 and 9001 + # 9001 not implemented + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # tcp services + # ------------- + - "traefik.tcp.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${SERVICE_PORT}" + - "traefik.tcp.services.${APPLICATION_NAME}-secure-svc.loadbalancer.server.port=${SECURE_SERVICE_PORT}" + # + # tcp routers + # ------------ + # limit router to mqtt ":1883" entrypoint + - "traefik.tcp.routers.${APPLICATION_NAME}-rtr.entrypoints=mqtt" + # set match criteria for router + - "traefik.tcp.routers.${APPLICATION_NAME}-rtr.rule=HostSNI(`*`)" + # assign svc target to routers + - "traefik.tcp.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to mqttsecure ":8883" entrypoint + - "traefik.tcp.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=mqttsecure" + # set match criteria for router + - "traefik.tcp.routers.${APPLICATION_NAME}-secure-rtr.rule=HostSNI(`${APPLICATION_NAME}.${DOMAINNAME}`) || HostSNI(`mqtt.${DOMAINNAME}`)" + # set router to be dedicated to secure requests only for the host specified in match criteria + - "traefik.tcp.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # passthrough tls + - "traefik.tcp.routers.${APPLICATION_NAME}-secure-rtr.tls.passthrough=true" + # generate certificates using following certresolver + - "traefik.tcp.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=sthomeresolver" + # assign svc target to routers + - "traefik.tcp.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-secure-svc" diff --git a/mysql-workbench/mysql-workbench.txt b/mysql-workbench/mysql-workbench.txt new file mode 100644 index 0000000..b28d817 --- /dev/null +++ b/mysql-workbench/mysql-workbench.txt @@ -0,0 +1,58 @@ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: mysql-workbench +Username: mysql-wb +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +mysql-wb PUID=3060 +mysql-wb PGID=3061 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*mysql-workbench" +# create following dataset if not present +zfs create SSD1/docker/data/mysql-workbench +zfs create SSD1/docker/data/mysql-workbench/config +chown -R mysql-wb:mysql-wb /mnt/SSD1/docker/data/mysql-workbench + +Create foldera +-------------- +mkdir -p /mnt/SSD1/docker/stacks/mysql-workbench/secrets + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in mysql-workbench folder, enter: +./cp2nas 192.168.2.2 +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/mysql-workbench/ +# This should copy stacks folder to /mnt/SSD1/docker/stacks/mysql-workbench + +Create secrets +-------------- +In Truenas shell: +# assuming you have already created secrets in mariab stacks folder: +cat /mnt/SSD1/docker/stacks/mariadb/secrets/mariadb_root_password > /mnt/SSD1/docker/stacks/mysql-workbench/secrets/mariadb_root_password +chown -R mysql-wb:mysql-wb /mnt/SSD1/docker/stacks/mysql-workbench/secrets/ +chmod -R 400 /mnt/SSD1/docker/stacks/mysql-workbench/secrets/ +# to list secrets in secrets dir +cd /mnt/SSD1/docker/stacks/mysql-workbench/secrets +for i in $(ls -1); do echo $i = `cat $i`; done | sort + +To open container shell +------------------------ +docker exec -it mysql-workbench-mysql-workbench-1 bash + +To log into database as root from container shell +------------------------------------------------- +mysql-workbench -u root -p +# Enter root password diff --git a/mysql-workbench/stacks/.env b/mysql-workbench/stacks/.env new file mode 100644 index 0000000..0174141 --- /dev/null +++ b/mysql-workbench/stacks/.env @@ -0,0 +1,22 @@ + +APPLICATION_NAME=mysql-workbench + +MEDIADIR=/mnt/stpool1/NData1/Media +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +PUID=3060 +PGID=3061 +MEDIA_PGID=3017 + + +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org +WEBUI_PORT=3000 + +MARIADB_DB_PORT=3306 +MARIADB_ROOT_PASSWORD_FILE=/run/secrets/mariadb_root_password + diff --git a/mysql-workbench/stacks/.mysql-workbench.env b/mysql-workbench/stacks/.mysql-workbench.env new file mode 100644 index 0000000..ffc445f --- /dev/null +++ b/mysql-workbench/stacks/.mysql-workbench.env @@ -0,0 +1,8 @@ + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +MARIADB_ROOT_PASSWORD_FILE=${MARIADB_ROOT_PASSWORD_FILE} + + diff --git a/mysql-workbench/stacks/compose.yml b/mysql-workbench/stacks/compose.yml new file mode 100644 index 0000000..8398682 --- /dev/null +++ b/mysql-workbench/stacks/compose.yml @@ -0,0 +1,63 @@ +name: mysql-workbench + +secrets: +# mariadb_database_name: +# file: ${SECRETSDIR}/mariadb_database_name +# mariadb_username: +# file: ${SECRETSDIR}/mariadb_username +# mariadb_password: +# file: ${SECRETSDIR}/mariadb_password + mariadb_root_password: + file: ${SECRETSDIR}/mariadb_root_password + +networks: + traefik-net: + external: true + mariadb-net: + external: true + +services: + mysql-workbench: + image: lscr.io/linuxserver/mysql-workbench:latest + hostname: mysql-workbench + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 + capabilities: [compute,video,graphics,utility] + cap_add: + - IPC_LOCK + volumes: + - "${DATADIR}/config:/config" +# ports: +# - 3000:3000 +# - 3001:3001 + restart: unless-stopped + env_file: .mysql-workbench.env + networks: + - traefik-net + - mariadb-net + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.${APPLICATION_NAME}-https-redirect.redirectscheme.permanent=true" + # + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=${APPLICATION_NAME}-https-redirect" + # + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=sthomeresolver" + # + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + diff --git a/mysql/mysql.txt b/mysql/mysql.txt new file mode 100644 index 0000000..33a9af4 --- /dev/null +++ b/mysql/mysql.txt @@ -0,0 +1,61 @@ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: mysql +Username: mysql +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +mysql PUID=3061 +mysql PGID=3062 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*mysql" +# create following datasets if not present +zfs create SSD1/docker/data/mysql +zfs create SSD1/docker/data/mysql/appdata +chown -R mysql:mysql /mnt/SSD1/docker/data/mysql + +Create folders +-------------- +mkdir -p /mnt/SSD1/docker/stacks/mysql/secrets + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in mysql folder, enter: +./cp2nas 192.168.2.2 +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/mysql/ +# This should copy stacks folder to /mnt/SSD1/docker/stacks/mysql + +Create secrets +-------------- +In Truenas shell: +cd /mnt/SSD1/docker/stacks/mysql/secrets +# echo -n 'your_mysql_database_name' > /mnt/SSD1/docker/stacks/mysql/secrets/mysql_database_name +# echo -n 'your_mysql_username' > /mnt/SSD1/docker/stacks/mysql/secrets/mysql_username +# openssl rand 36 | base64 -w 0 | sed 's/[\$,\#,/,+,=]//g' | cut -c -32 | tr -d '\n' > /mnt/SSD1/docker/stacks/mysql/secrets/mysql_password +openssl rand 60 | base64 -w 0 | sed 's/[\$,\#,/,+,=]//g' | cut -c -56 | tr -d '\n' > /mnt/SSD1/docker/stacks/mysql/secrets/mysql_root_password +chown -R mysql:mysql /mnt/SSD1/docker/stacks/mysql/secrets/ +chmod -R 400 /mnt/SSD1/docker/stacks/mysql/secrets/ +# to list secrets in secrets dir +cd /mnt/SSD1/docker/stacks/mysql/secrets +for i in $(ls -1); do echo $i = `cat $i`; done | sort + +To open container shell +------------------------ +docker exec -it mysql-mysql-1 bash + +To log into database as root from container shell +------------------------------------------------- +mysql -u root -p +# Enter root password diff --git a/mysql/stacks/.env b/mysql/stacks/.env new file mode 100644 index 0000000..cc3892f --- /dev/null +++ b/mysql/stacks/.env @@ -0,0 +1,20 @@ + +APPLICATION_NAME=mysql + +MEDIADIR=/mnt/stpool1/NData1/Media +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +PUID=3061 +PGID=3062 +MEDIA_PGID=3017 + +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org + +SERVICE_PORT=3306 +MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_password + diff --git a/mysql/stacks/.mysql.env b/mysql/stacks/.mysql.env new file mode 100644 index 0000000..bc92c91 --- /dev/null +++ b/mysql/stacks/.mysql.env @@ -0,0 +1,16 @@ + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +MYSQL_ROOT_PASSWORD_FILE=${MYSQL_ROOT_PASSWORD_FILE} + +# REMOTE_SQL=http://URL1/your.sql,https://URL2/your.sql + +# MYSQL_DATABASE: 'db' +# # So you don't have to use root, but you can if you like +# MYSQL_USER: 'user' +# # You can use whatever password you like +# MYSQL_PASSWORD: 'password' +# # Password for root access +# MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} \ No newline at end of file diff --git a/mysql/stacks/compose.yml b/mysql/stacks/compose.yml new file mode 100644 index 0000000..f5cd504 --- /dev/null +++ b/mysql/stacks/compose.yml @@ -0,0 +1,56 @@ +name: mysql + +secrets: + mysql_root_password: + file: ${SECRETSDIR}/mysql_root_password + +networks: + mysql-net: + external: true + traefik-net: + external: true + +services: + mysql: + image: mysql:latest # mysql:5.7 + restart: always + env_file: .mysql.env + user: ${PUID}:${PGID} + volumes: + - "${DATADIR}/appdata:/var/lib/mysql" + secrets: + - mysql_root_password + networks: + - mysql-net + - traefik-net + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # tcp service + # ----------- + - "traefik.tcp.services.${APPLICATION_NAME}-tcp-svc.loadbalancer.server.port=${SERVICE_PORT}" + # + # tcp routers + # ----------- + # limit router to mysql ":9306" entrypoint + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-rtr.entrypoints=mysql" + # set match criteria for router, since this is not tls, header might not contain hostsni field; we're forced to use wildcard + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-rtr.rule=HostSNI(`*`)" + # assign svc target to router + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-rtr.service=${APPLICATION_NAME}-tcp-svc" +###### mysql with tls via traefik not working +# # +# # limit router to mysql ":9306" entrypoint +# - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.entrypoints=mysql" +# # set match criteria for router +# - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.rule=HostSNI(`${APPLICATION_NAME}.${DOMAINNAME}`)" +# # set router to be dedicated to secure requests only for the hosts specified in match criteria +# - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls=true" +# # forward requests "as is" keeping all data encrypted. +# - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls.passthrough=true" +# - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls.options=tls-opts@file" +# # generate certificates using following certresolver +# - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls.certresolver=sthomeresolver" +# # assign svc target to router +# - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.service=${APPLICATION_NAME}-tcp-svc" \ No newline at end of file diff --git a/networks/stacks/compose.yml b/networks/stacks/compose.yml new file mode 100644 index 0000000..1d81869 --- /dev/null +++ b/networks/stacks/compose.yml @@ -0,0 +1,88 @@ + +name: networks + +networks: + macvlan0: + name: macvlan0 + driver: macvlan + driver_opts: + parent: br1 + com.docker.network.macvlan.mode: bridge + com.docker.network.bridge.name: "br-locallan" + ipam: + config: + - subnet: 192.168.2.0/24 + gateway: 192.168.2.1 + + traefik-net: + name: traefik-net + attachable: true + driver: bridge + ipam: + config: + - subnet: 10.255.224.0/20 # Range: 10.255.224.1 - 10.255.239.254 + driver_opts: + # NB! bridge name should be 15 characters or less + com.docker.network.bridge.name: "br-traefik" + postgres-net: + name: postgres-net + driver: bridge + internal: true + driver_opts: + com.docker.network.bridge.name: "br-postgres" + mariadb-net: + name: mariadb-net + driver: bridge + internal: true + driver_opts: + com.docker.network.bridge.name: "br-mariadb" + mysql-net: + name: mysql-net + driver: bridge + internal: true + driver_opts: + com.docker.network.bridge.name: "br-mysql" + authentik-net: + name: authentik-net + driver: bridge + internal: true + driver_opts: + com.docker.network.bridge.name: "br-authentik" + fireflyiii-net: + name: fireflyiii-net + driver: bridge + internal: true + driver_opts: + com.docker.network.bridge.name: "br-fireflyiii" + vaultwarden-net: + name: vaultwarden-net + driver: bridge + internal: true + driver_opts: + com.docker.network.bridge.name: "br-vaultwarden" + digikam-net: + name: digikam-net + driver: bridge + internal: true + driver_opts: + com.docker.network.bridge.name: "br-digikam" + +services: + netbb: + image: busybox + hostname: netsvc2 + networks: + - traefik-net + - postgres-net + - mariadb-net + - mysql-net + - authentik-net + - fireflyiii-net + - vaultwarden-net + - digikam-net + - macvlan0 + + + + + diff --git a/nextcloud/nextcloud_jm.txt b/nextcloud/nextcloud_jm.txt new file mode 100644 index 0000000..b532306 --- /dev/null +++ b/nextcloud/nextcloud_jm.txt @@ -0,0 +1,297 @@ +# https://github.com/nextcloud/docker +# https://github.com/nextcloud/docker?tab=readme-ov-file#running-this-image-with-docker-compose +# https://api.onlyoffice.com/docs/docs-api/get-started/ready-to-use-connectors/nextcloud-integration/ + +Create user and group +--------------------- +Credentials -> Local Groups -> Add +GID: 33 +Name: www-data +Save +Credentials -> Local Users -> Add +Full Name: www-data +Username: www-data +Disable Password: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Data: +Objects: +Check public to select all objects +Click Backup +# After backup, verify presence of backup file: +ls -al /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) +# copy backup file(s) to onlyoffice backups folder, replacing $(date -I) with date when backup was made if not today +mkdir /mnt/SSD1/docker/data/onlyoffice/documentserver/pgbackups/$(date -I)/ +cp -vr /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I)/onlyoffice-backup.sql /mnt/SSD1/docker/data/onlyoffice/documentserver/pgbackups/$(date -I)/ +chown -R pguser:pguser /mnt/SSD1/docker/data/onlyoffice/documentserver/pgbackups/ + +Migrating database +------------------ +# In truenas shell +jlmkr shell docker +cd /opt/stacks/onlyoffice +docker compose down +# remove all files/folders from pgdata; if any are already in this folder with data to be retained, move it to another folder before executing next command +rm -r /mnt/data/onlyoffice/documentserver/pgdata/* +docker compose up -d +# get the container names +docker ps +# After successfull startup of documentserver and postgres, stop documentserver from docker cmd line +docker stop onlyoffice-documentserver-1 +docker exec onlyoffice-postgresql-1 psql -U -d postgres -c "DROP DATABASE \"\";" +docker exec onlyoffice-postgresql-1 psql -U -d postgres -c "CREATE DATABASE \"\";" +docker exec onlyoffice-postgresql-1 psql -U -d -f /mnt/backups/$(date -I)/onlyoffice-backup.sql # replace $(date -I) with the appropriate date +docker stop onlyoffice-documentserver-1 + +Stop truenas onlyoffice +--------------------------- +# In truenas shell +heavyscript app --stop onlyoffice +# NB: Do NOT stop onlyoffice with truenas gui + +If you need to log into db +-------------------------- +docker exec -it onlyoffice_postgresql bash +psql -U -d diff --git a/onlyoffice/stacks/.communityserver.env b/onlyoffice/stacks/.communityserver.env new file mode 100644 index 0000000..131f179 --- /dev/null +++ b/onlyoffice/stacks/.communityserver.env @@ -0,0 +1,24 @@ +# +# environment variables for communityserver +# +PUID=${PUID} +PGID=${PUID} +TZ=${TZ} +PORT=${WEBUI_PORT} #80 + +MYSQL_SERVER_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} +MYSQL_SERVER_DB_NAME=${MYSQL_DB_NAME} +MYSQL_SERVER_USER=${MYSQL_USER} +MYSQL_SERVER_PASS=${MYSQL_PASSWORD} +MAIL_SERVER_API_HOST=${MAIL_SERVER_IP} +MAIL_SERVER_DB_NAME=${MAIL_SERVER_DB_NAME} +MAIL_SERVER_DB_PORT=${MYSQL_PORT} +MAIL_SERVER_DB_USER=${MYSQL_ROOT_USER} +MAIL_SERVER_DB_PASS=${MAIL_SERVER_DB_PASS} + +DOCUMENT_SERVER_JWT_ENABLED=${JWT_ENABLED} +DOCUMENT_SERVER_JWT_SECRET=${JWT_SECRET} +DOCUMENT_SERVER_JWT_HEADER=${DOCUMENT_SERVER_JWT_HEADER} + +# https://github.com/thomisus/Docker-DocumentServer/pkgs/container/onlyoffice-documentserver-unlimited#installing-mysql +# https://medium.com/@chrischuck35/how-to-create-a-mysql-instance-with-docker-compose-1598f3cc1bee \ No newline at end of file diff --git a/onlyoffice/stacks/.documentserver.env b/onlyoffice/stacks/.documentserver.env new file mode 100644 index 0000000..7b91a30 --- /dev/null +++ b/onlyoffice/stacks/.documentserver.env @@ -0,0 +1,114 @@ +# +# environment variables for documentserver +# +PUID=${PUID} +PGID=${PUID} +TZ=${TZ} +PORT=${WEBUI_PORT} #80 + +# Advanced configuration option for turning off the HSTS configuration. Applicable only when SSL is in use. Defaults to true. +ONLYOFFICE_HTTPS_HSTS_ENABLED= + +# Advanced configuration option for setting the HSTS max-age in the onlyoffice nginx vHost configuration. Applicable only when SSL is in use. Defaults to 31536000. +ONLYOFFICE_HTTPS_HSTS_MAXAGE= + +# The path to the SSL certificate to use. Defaults to /var/www/onlyoffice/Data/certs/tls.crt. +SSL_CERTIFICATE_PATH= + +# The path to the SSL certificate's private key. Defaults to /var/www/onlyoffice/Data/certs/tls.key. +SSL_KEY_PATH= + +# The path to the Diffie-Hellman parameter. Defaults to /var/www/onlyoffice/Data/certs/dhparam.pem. +SSL_DHPARAM_PATH= + +# Enable verification of client certificates using the CA_CERTIFICATES_PATH file. Defaults to false +SSL_VERIFY_CLIENT= + +# The NODE_EXTRA_CA_CERTS to extend CAs with the extra certificates for Node.js. Defaults to /var/www/onlyoffice/Data/certs/extra-ca-certs.pem. +NODE_EXTRA_CA_CERTS= + +# The database type. Supported values are postgres, mariadb, mysql, mssql or oracle. Defaults to postgres. +DB_TYPE=postgres + +# The database server port number. +DB_PORT=${POSTGRES_PORT} + +# The name of a database to use. Should be existing on container startup. +# DB_NAME_FILE=${POSTGRES_DB_FILE} +DB_NAME=${POSTGRES_DB} + +# The new user name with superuser permissions for the database account. +# DB_USER_FILE=${POSTGRES_USER_FILE} +DB_USER=${POSTGRES_USER} + +# The password set for the database account. +# DB_PWD_FILE=${POSTGRES_PASSWORD_FILE} +DB_PWD=${POSTGRES_PASSWORD} + +# The message broker type. Supported values are rabbitmq or activemq. Defaults to rabbitmq. +AMQP_TYPE=rabbitmq + +# The Redis server port number. +REDIS_SERVER_PORT=${REDIS_PORT} + +# The Redis server password. The password is not set by default. +REDIS_SERVER_PASS=${REDIS_PASSWORD} + +# Defines the number of nginx worker processes. +NGINX_WORKER_PROCESSES= + +# Sets the maximum number of simultaneous connections that can be opened by a nginx worker process. +NGINX_WORKER_CONNECTIONS= + +# Defines secret for the nginx config directive secure_link_md5. Defaults to random string. +SECURE_LINK_SECRET= + +# Specifies the enabling the JSON Web Token validation by the ONLYOFFICE Document Server. Defaults to true. +JWT_ENABLED=${JWT_ENABLED} + +# Defines the secret key to validate the JSON Web Token in the request to the ONLYOFFICE Document Server. Defaults to random value. +JWT_SECRET=${JWT_SECRET} + +# Defines the http header that will be used to send the JSON Web Token. Defaults to Authorization. +JWT_HEADER=${JWT_HEADER} + +# Specifies the enabling the token validation in the request body to the ONLYOFFICE Document Server. Defaults to false. +JWT_IN_BODY=true + +# Specifies the enabling the wopi handlers. Defaults to false. +WOPI_ENABLED= + +# Defines if it is allowed to connect meta IP address or not. Defaults to false. +ALLOW_META_IP_ADDRESS= + +# Defines if it is allowed to connect private IP address or not. Defaults to false. +ALLOW_PRIVATE_IP_ADDRESS= + +# Set to trueif using selfsigned certificates for your storage server e.g. Nextcloud. Defaults to false +USE_UNAUTHORIZED_STORAGE= + +# When 'true' regenerates fonts list and the fonts thumbnails etc. at each start. Defaults to true +GENERATE_FONTS= + +# Specifies the enabling StatsD for ONLYOFFICE Document Server. Defaults to false. +METRICS_ENABLED= + +# Defines StatsD listening host. Defaults to localhost. +METRICS_HOST= + +# Defines StatsD listening port. Defaults to 8125. +METRICS_PORT= + +# Defines StatsD metrics prefix for backend services. Defaults to ds.. +METRICS_PREFIX= + +# Defines the domain for Let's Encrypt certificate. +LETS_ENCRYPT_DOMAIN=${CERT_LETS_ENCRYPT_DOMAIN} + +# Defines the domain administator mail address for Let's Encrypt certificate. +LETS_ENCRYPT_MAIL=${CERT_LETS_ENCRYPT_MAIL} + +# Defines whether to enable default plugins. Defaults to false. +PLUGINS_ENABLED= + + diff --git a/onlyoffice/stacks/.env b/onlyoffice/stacks/.env new file mode 100644 index 0000000..eda4c46 --- /dev/null +++ b/onlyoffice/stacks/.env @@ -0,0 +1,64 @@ +# +# values to be used for substitution by docker compose in compose.yml AND .*.env files +# +APPLICATION_NAME=onlyoffice + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media + +BULKSTOREDIR=/mnt/stpool1/NData2/bulkstore + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org +BULKSTORE=/mnt/bulkstore/onlyoffice + +PUID=3049 +PGID=3048 +TZ=Africa/Johannesburg +WEBUI_PORT=80 +MAIL_SERVER_IP=10.0.0.61 + +CERT_LETS_ENCRYPT_DOMAIN=onlyoffice.sthome.org +CERT_LETS_ENCRYPT_MAIL=stuurmcp@telkomsa.net + +# +# Generate DB_PASSWORD with: +# openssl rand 36 | base64 -w 0 > /mnt/SSD1/docker/stacks/onlyoffice/secrets/onlyoffice_postgresql_password + +POSTGRES_PORT=5432 +POSTGRES_DB_FILE=/run/secrets/onlyoffice_postgresql_database +POSTGRES_USER_FILE=/run/secrets/onlyoffice_postgresql_username +POSTGRES_PASSWORD_FILE=/run/secrets/onlyoffice_postgresql_password +# onlyoffice does not support docker secrets, so we have to specify in clear text +POSTGRES_USER=onlyoffice +POSTGRES_DB=onlyoffice +POSTGRES_PASSWORD=zHLIEq8fJu6qlDRIb0bDkv3QNR6fET7ywRwgDeZa53Q0AEvV + +MYSQL_PORT=3306 +MYSQL_ROOT_USER=root +MYSQL_USER=onlyoffice +MYSQL_DB_NAME=onlyoffice +MYSQL_PASSWORD=vOVHV7wfuAj4QzzLFbolntWf0Io+CmxoKp2KAMFlw2tYQ8z7 +MYSQL_ROOT_PASSWORD=du4WD8y+sqbPeJgkqbl6c4zf179fRtEHFW8lTm58UPVE6Abn8gkarkTSvIPyUJsD + +MAIL_SERVER_DB_NAME=onlyoffice-mailserver +MAIL_SERVER_DB_PASS=WNnqrayLW/nFsFEjN1fVeqSvrmwABK+vGACeXhVlFRS47oQI +MAIL_SERVER_API_HOST=${MAIL_SERVER_IP} + +REDIS_PORT=6379 +REDIS_PASSWORD_FILE=/run/secrets/onlyoffice_redis_password +# redis does not support docker secrets, so we have to specify in clear text +REDIS_PASSWORD=uLlXF7byd9BcXcKRX63b928lnkDmYFUnamtnaPWCsdaWAWieTH + +JWT_ENABLED=true +JWT_HEADER=Authorization +DOCUMENT_SERVER_JWT_HEADER=AuthorizationJwt +# Generate JWT_SECRET with: +# echo -n $(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 32) > /mnt/SSD1/docker/stacks/onlyoffice/secrets/onlyoffice_jwt_secret +JWT_SECRET_FILE=/run/secrets/onlyoffice_jwt_secret # we leave this in case onlyoffice supports docker secrets in future +# onlyoffice does not support docker secrets, so we have to specify in clear text +JWT_SECRET=sEknyxjVGK7PaDgOMsV8rsHc79A6frHp diff --git a/onlyoffice/stacks/.mailserver.env b/onlyoffice/stacks/.mailserver.env new file mode 100644 index 0000000..80b441f --- /dev/null +++ b/onlyoffice/stacks/.mailserver.env @@ -0,0 +1,13 @@ +# +# environment variables for mailserver +# +PUID=${PUID} +PGID=${PUID} +TZ=${TZ} +PORT=${WEBUI_PORT} #80 + +MYSQL_SERVER_PORT=${MYSQL_PORT} +MYSQL_ROOT_USER=${MYSQL_ROOT_USER} +MYSQL_ROOT_PASSWD=${MYSQL_ROOT_PASSWORD} +MYSQL_SERVER_DB_NAME=${MYSQL_DB_NAME} +# MYSQL_PASS=${MYSQL_PASSWORD} diff --git a/onlyoffice/stacks/.mysql.env b/onlyoffice/stacks/.mysql.env new file mode 100644 index 0000000..a5cb54e --- /dev/null +++ b/onlyoffice/stacks/.mysql.env @@ -0,0 +1,10 @@ + +PUID=${PUID} +PGID=${PUID} +TZ=${TZ} +PORT=${WEBUI_PORT} #80 + +# MYSQL_DATABASE='db' +# MYSQL_USER='user' +MYSQL_PASSWORD=$MYSQL_PASSWORD} +MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \ No newline at end of file diff --git a/onlyoffice/stacks/.postgresql.env b/onlyoffice/stacks/.postgresql.env new file mode 100644 index 0000000..5eef283 --- /dev/null +++ b/onlyoffice/stacks/.postgresql.env @@ -0,0 +1,10 @@ + +PUID=70 +PGID=70 +TZ=${TZ} + +DB_PORT=${POSTGRES_PORT} +POSTGRES_DB_FILE=${POSTGRES_DB_FILE} +POSTGRES_USER_FILE=${POSTGRES_USER_FILE} +POSTGRES_PASSWORD_FILE=${POSTGRES_PASSWORD_FILE} +POSTGRES_HOST_AUTH_METHOD=scram-sha-256 # WARNING: setting this to "trust" will allow logins without password for all connections diff --git a/onlyoffice/stacks/.redis.env b/onlyoffice/stacks/.redis.env new file mode 100644 index 0000000..b58830c --- /dev/null +++ b/onlyoffice/stacks/.redis.env @@ -0,0 +1,9 @@ + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +REDIS_PORT=${REDIS_PORT} + +# redis does not support docker secrets +#REDIS_PASSWORD_FILE=${REDIS_PASSWORD_FILE} diff --git a/onlyoffice/stacks/compose.yml b/onlyoffice/stacks/compose.yml new file mode 100644 index 0000000..a1ff522 --- /dev/null +++ b/onlyoffice/stacks/compose.yml @@ -0,0 +1,239 @@ +# before stopping only-office execute: +# docker exec documentserver-prepare4shutdown.sh +# +# https://gist.github.com/kvaps/6ac945e6c2e2e41bd536b7486a7dea4a + +name: onlyoffice + +secrets: + onlyoffice_postgresql_database: + file: ${SECRETSDIR}/onlyoffice_postgresql_database + onlyoffice_postgresql_password: + file: ${SECRETSDIR}/onlyoffice_postgresql_password + onlyoffice_postgresql_username: + file: ${SECRETSDIR}/onlyoffice_postgresql_username + onlyoffice_jwt_secret: + file: ${SECRETSDIR}/onlyoffice_jwt_secret + onlyoffice_redis_password: + file: ${SECRETSDIR}/onlyoffice_redis_password + +networks: + traefik-net: + external: true + postgres-net: + external: true + backend: + name: onlyoffice-net + driver: bridge + driver_opts: + com.docker.network.bridge.name: "br-onlyoffice" + +services: + documentserver: + image: "onlyoffice/documentserver:latest" + hostname: onlyoffice_documentserver + env_file: .documentserver.env + privileged: true + stdin_open: true + tty: true + volumes: + - /etc/localtime:/etc/localtime:ro + - /run/dbus:/run/dbus:ro + - "${DATADIR}/redis:/var/lib/redis" + - "${DATADIR}/rabbitmq:/var/lib/rabbitmq" + - "${DATADIR}/pgdata:/var/lib/postgresql" + - "${DATADIR}/documentserver/logs:/var/log/onlyoffice" + - "${DATADIR}/documentserver/data:/var/www/onlyoffice/Data" + - "${DATADIR}/documentserver/lib:/var/lib/onlyoffice" +# - "${DATADIR}/documentserver/public:/var/www/onlyoffice/documentserver-example/public/files" +# - "${DATADIR}/documentserver/fonts:/usr/share/fonts" + networks: + - traefik-net + - backend + - postgres-net + secrets: + - onlyoffice_postgresql_database + - onlyoffice_postgresql_password + - onlyoffice_postgresql_username + - onlyoffice_jwt_secret + - onlyoffice_redis_password + environment: + # The IP address or the name of the host where the database server is running. + DB_HOST: onlyoffice_postgresql + # The IP address or the name of the host where the Redis server is running. + REDIS_SERVER_HOST: onlyoffice_rabbitmq + # The AMQP URI to connect to message broker server. + AMQP_URI: amqp://guest:guest@onlyoffice_rabbitmq + depends_on: + postgresql: + condition: service_healthy + rabbitmq: + condition: service_healthy + redis: + condition: service_started + restart: unless-stopped + stop_grace_period: 60s + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + - "traefik.http.middlewares.onlyoffice_documentserver-https-redirect.redirectscheme.scheme=https" + - "traefik.http.middlewares.onlyoffice_documentserver-https-redirect.redirectscheme.permanent=true" + # + - "traefik.http.services.onlyoffice_documentserver-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + - "traefik.http.routers.onlyoffice_documentserver-rtr.entrypoints=web" + - "traefik.http.routers.onlyoffice_documentserver-rtr.rule=Host(`onlyoffice.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.onlyoffice_documentserver-rtr.middlewares=onlyoffice_documentserver-https-redirect" + - "traefik.http.routers.onlyoffice_documentserver-rtr.service=onlyoffice_documentserver-svc" + # + - "traefik.http.routers.onlyoffice_documentserver-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.onlyoffice_documentserver-secure-rtr.rule=Host(`onlyoffice.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.onlyoffice_documentserver-secure-rtr.tls=true" + - "traefik.http.routers.onlyoffice_documentserver-secure-rtr.tls.certresolver=sthomeresolver" + - "traefik.http.routers.onlyoffice_documentserver-secure-rtr.service=onlyoffice_documentserver-svc" + + rabbitmq: + image: rabbitmq + restart: unless-stopped + healthcheck: + test: rabbitmq-diagnostics -q ping + interval: 30s + timeout: 30s + retries: 3 + networks: + backend: + aliases: ["onlyoffice_rabbitmq"] + +# https://stackoverflow.com/questions/66738931/how-to-set-password-for-redis-server +# I managed to set the password permanently for the default user. Adding these 2 parameters in the file "redis.conf" requirepass newpass123 masterauth newpass123 And in the file "sentinel.conf" sentinel auth-pass mymaster newpass123 Thanks – +#user14867757 +# CommentedMar 24, 2021 at 4:19 + redis: + image: docker.io/library/redis:alpine + #command: --save 60 1 --loglevel warning + command: sh -c "redis-server --requirepass ${REDIS_PASSWORD}" && --save 60 1 && --loglevel warning + env_file: .redis.env + restart: unless-stopped + expose: + - ${REDIS_PORT} +# healthcheck: +# test: ["CMD-SHELL", "redis-cli ping | grep PONG"] +# start_period: 20s +# interval: 30s +# retries: 5 +# timeout: 3s + secrets: + - onlyoffice_redis_password + networks: + backend: + aliases: ["onlyoffice_redis"] + volumes: + - "$DATADIR/redis/data:/data" + +# mailserver: +# init: true +# hostname: "mail.${DOMAINNAME}" +# image: onlyoffice/mailserver +# env_file: .mailserver.env +# networks: +# backend: +# aliases: ["onlyoffice_mailserver"] +# privileged: true +# stdin_open: true +# tty: true +# restart: always +# ports: +# - 25:25 +# - 143:143 +# - 587:587 +# environment: +# MYSQL_SERVER: onlyoffice_mysql +# volumes: +# - "${BULKSTORE}/mailserver/data:/var/vmail" +# - "${DATADIR}/mailserver/data/certs:/etc/pki/tls/mailserver" +# - "${DATADIR}/mailserver/logs:/var/log" +# +# communityserver: +# image: onlyoffice/communityserver +# env_file: .communityserver.env +# networks: +# backend: +# aliases: ["onlyoffice_communityserver"] +# stdin_open: true +# tty: true +# privileged: true +# restart: always +## ports: +## - 80:80 +## - 443:443 +## - 5222:5222 +# cgroup: host +# environment: +# MYSQL_SERVER_HOST: onlyoffice_mysql +# MAIL_SERVER_DB_HOST: onlyoffice_mysql +# DOCUMENT_SERVER_PORT_80_TCP_ADDR: onlyoffice_documentserver +# volumes: +# - "${DATADIR}/communityserver/data:/var/www/onlyoffice/Data" +# - "${DATADIR}/communityserver/logs:/var/log/onlyoffice" +# - "${DATADIR}/communityserver/letsencrypt:/etc/letsencrypt" +# - "/sys/fs/cgroup:/sys/fs/cgroup:rw" +# labels: +# - traefik.enable=true +# - traefik.docker.network=traefik-net +# # +# - "traefik.http.middlewares.onlyoffice_communityserver-https-redirect.redirectscheme.scheme=https" +# - "traefik.http.middlewares.onlyoffice_communityserver-https-redirect.redirectscheme.permanent=true" +# # +# - "traefik.http.services.onlyoffice_communityserver-svc.loadbalancer.server.port=${WEBUI_PORT}" +# # +# - "traefik.http.routers.onlyoffice_communityserver-rtr.entrypoints=web" +# - "traefik.http.routers.onlyoffice_communityserver-rtr.rule=Host(`onlyoffice_communityserver.${DOMAINNAME}`)&& PathPrefix(`/`)" +# - "traefik.http.routers.onlyoffice_communityserver-rtr.middlewares=onlyoffice_communityserver-https-redirect" +# - "traefik.http.routers.onlyoffice_communityserver-rtr.service=onlyoffice_communityserver-svc" +# # +# - "traefik.http.routers.onlyoffice_communityserver-secure-rtr.entrypoints=websecure" +# - "traefik.http.routers.onlyoffice_communityserver-secure-rtr.rule=Host(`onlyoffice_communityserver.${DOMAINNAME}`)&& PathPrefix(`/`)" +# - "traefik.http.routers.onlyoffice_communityserver-secure-rtr.tls=true" +# - "traefik.http.routers.onlyoffice_communityserver-secure-rtr.tls.certresolver=sthomeresolver" +# - "traefik.http.routers.onlyoffice_communityserver-secure-rtr.service=onlyoffice_communityserver-svc" + + postgresql: + image: postgres:16-alpine + hostname: "onlyoffice_postgresql" + shm_size: 128mb # https://hub.docker.com/_/postgres + restart: unless-stopped + env_file: .postgresql.env + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + networks: + postgres-net: + aliases: ["onlyoffice_postgresql"] + secrets: + - onlyoffice_postgresql_database + - onlyoffice_postgresql_password + - onlyoffice_postgresql_username + volumes: + - "${DATADIR}/pgdata:/var/lib/postgresql/data" + - "${DATADIR}/pgbackups:/mnt/backups" + +# mysql: +# image: mysql:5.7 +# restart: always +# env_file: .mysql.env +# networks: +# backend: +# aliases: ["onlyoffice_mysql"] +# ports: +# # : +# - '3306:3306' +# expose: +# # Opens port 3306 on the container +# - '3306' +# # Where our data will be persisted +# volumes: +# - "${DATADIR}/mysqldata:/var/lib/mysql" diff --git a/overseerr/overseerr_jm.txt b/overseerr/overseerr_jm.txt new file mode 100644 index 0000000..28a3be3 --- /dev/null +++ b/overseerr/overseerr_jm.txt @@ -0,0 +1,127 @@ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: overseerr +Username: overseer +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +overseer UID: 3031 +overseer GID: 3030 + +Create datasets +--------------- +/mnt/SSD1/docker/data/overseerr +/mnt/SSD1/docker/data/overseerr/config +# Set Owner:Group to overseer:overseer + +Create folder +------------- +mkdir /opt/stacks/overseerr + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in overseerr folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/overseerr/ +# This should copy compose.yaml, .env and secrets to /mnt/SSD1/docker/stacks/overseerr + +Migrating data from old overseerr (source) to newly installed one (target) +-------------------------------------------------------------------------- +# Stop old/source overseerr +heavyscript app --stop overseerr +# Stop new/target overseerr media server +# On Dockge, select overseerr and click stop +# Copy the source Library to target folder: +cp -pr /mnt/stpool1/apps/overseerr/* /mnt/SSD1/docker/data/overseerr/config/ +chown -R overseer:overseer /mnt/SSD1/docker/data/overseerr/config/ + +Obtaining radarr/sonarr hostname +-------------------------------- +Use the following hostname in overseerr settings for sonarr/radarr depending on given scenario: +Scenario Hostname to use +~~~~~~~~ ~~~~~~~~~~~~~~~ +Overseerr, radarr and sonarr are services in the same project localhost +Overseerr in separate project; radarr and sonarr part of gluetun-arr project alias of gluetun service + +How to get alias of alias of gluetun-arr service +------------------------------------------------ +Assuming that gluetun service has an alias configured under the networks stanza +In docker shell: +cd /opt/stacks/gluetun-arr +docker compose config | grep -A 1 "aliases" + +Overseerr settings +------------------ +Open overseerr web app using browser +Sign in +Settings->Plex window, enter "plex.sthome.org" for Hostname or IP Address +Click on Save Changes +You should get a "Plex connection established successfully" in top right corner +Leave "Use SSL" checked +Click on Sync Libraries +Select Libraries to sync and click on Scan Libraries +After scan completes, click Continue +Settings->Services +Click on Edit Radarr Server +Default Server: +4K Server: +Server Name: radarr +Hostname or IP Address: +Port: 7878 +Use SSL: +API Key: settings->general->API Key> +URL Base: +Click on Test +You should get a "Radarr connection established successfully" in top right corner +Quality Profile: +Minimum Availability: +Root Folder: +Email: +UID: 5050 +Create New Primary Group: +Primary Group: pgadmin +Create Home Directory: +Samba Authentication: +Save + +pgadmin UID: 5050 +pgadmin GID: 5050 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*pgadmin" +# create following datasets if not present +zfs create SSD1/docker/data/pgadmin +zfs create SSD1/docker/data/pgadmin/config +chown -R pgadmin:pgadmin /mnt/SSD1/docker/data/pgadmin + +Create folders +-------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/pgadmin/secrets + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in pgadmin folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/pgadmin/ +# This should copy pgadmin stacks folder to /mnt/SSD1/docker/stacks/pgadmin + +Create secrets +-------------- +# In Truenas shell: +cd /mnt/SSD1/docker/stacks/pgadmin/secrets +echo -n 'your_pgadmin_password' > /mnt/SSD1/docker/stacks/pgadmin/secrets/pgadmin_default_password +# restrict access +cd /mnt/SSD1/docker/stacks/pgadmin +chown -R pgadmin:pgadmin secrets/ +chmod -R 400 secrets/ + +Migrating config data +--------------------- +# Stop pgadmin on truenas, in truenas shell +heavyscript app --stop pgadmin +# copy config storage to new install data folder +cp -pr /mnt/stpool1/apps/pgadmin/. /mnt/SSD1/docker/data/pgadmin/config/ +chown -R pgadmin:pgadmin /mnt/SSD1/docker/data/pgadmin/ + diff --git a/pgadmin/stacks/.env b/pgadmin/stacks/.env new file mode 100644 index 0000000..bb75983 --- /dev/null +++ b/pgadmin/stacks/.env @@ -0,0 +1,20 @@ + +APPLICATION_NAME=pgadmin + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org + +PUID=5050 +PGID=5050 +TZ=Africa/Johannesburg +WEBUI_PORT=80 + +PGADMIN_DEFAULT_EMAIL_FILE=/run/secrets/pgadmin_default_email +PGADMIN_DEFAULT_PASSWORD_FILE=/run/secrets/pgadmin_default_password \ No newline at end of file diff --git a/pgadmin/stacks/.pgadmin.env b/pgadmin/stacks/.pgadmin.env new file mode 100644 index 0000000..449fe8f --- /dev/null +++ b/pgadmin/stacks/.pgadmin.env @@ -0,0 +1,25 @@ +# https://www.pgadmin.org/docs/pgadmin4/latest/container_deployment.html + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL_FILE} +PGADMIN_DEFAULT_PASSWORD_FILE=${PGADMIN_DEFAULT_PASSWORD_FILE} + +# PGADMIN_DISABLE_POSTFIX= +# PGADMIN_ENABLE_TLS= +# PGADMIN_LISTEN_ADDRESS= +# PGADMIN_LISTEN_PORT= +# PGADMIN_SERVER_JSON_FILE= +# GUNICORN_ACCESS_LOGFILE= +# GUNICORN_LIMIT_REQUEST_LINE= +# GUNICORN_THREADS= + + +# PGADMIN_CONFIG_* +# This is a variable prefix that can be used to override any of the configuration options in pgAdmin’s config.py file. Add the PGADMIN_CONFIG_ prefix to any variable name from config.py and give the value in the format ‘string value’ for strings, True/False for booleans or 123 for numbers +# examples +# PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION=True +# PGADMIN_CONFIG_LOGIN_BANNER="Authorised users only!" +# PGADMIN_CONFIG_CONSOLE_LOG_LEVEL=10 diff --git a/pgadmin/stacks/compose.yml b/pgadmin/stacks/compose.yml new file mode 100644 index 0000000..7210f34 --- /dev/null +++ b/pgadmin/stacks/compose.yml @@ -0,0 +1,56 @@ + +name: pgadmin + +secrets: + pgadmin_default_password: + file: ${SECRETSDIR}/pgadmin_default_password + pgadmin_default_email: + file: ${SECRETSDIR}/pgadmin_default_email + +networks: + traefik-net: + external: true + postgres-net: + external: true + authentik-net: + external: true + fireflyiii-net: + external: true + vaultwarden-net: + external: true + +services: + pgadmin: + image: dpage/pgadmin4 + env_file: .pgadmin.env + hostname: pgadmin + networks: + - traefik-net + - postgres-net + - authentik-net + - fireflyiii-net + - vaultwarden-net + restart: unless-stopped + volumes: + - "${DATADIR}/config:/var/lib/pgadmin" + secrets: + - pgadmin_default_password + - pgadmin_default_email + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" diff --git a/photoview/cp2nas.ps1 b/photoview/cp2nas.ps1 new file mode 100644 index 0000000..6778989 --- /dev/null +++ b/photoview/cp2nas.ps1 @@ -0,0 +1,57 @@ +############### MAIN ############### +$Main = +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + [Parameter(Mandatory=$false)] + [string[]] $apps + ) + If($PSBoundParameters.ContainsKey("apps")) { + foreach ($appname in $apps) + { + copyfolder $destHost "$appname\stacks" $appname + } + } + else { + $appname="$pwd".Split("\\")[-1] + copyfolder $destHost "stacks" $appname + } +} + +################################### +Function copyfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $appname + ) + if (-Not(Test-Path -Path $srcdir)) { + Write-Host "Source path doesn't exist: ""$PSScriptRoot\$srcdir\*.*"". No files copied!" -ForegroundColor Red + Write-Host "Usage: in app folder : ./cp2nas DEST|IP" + Write-Host " in app parent folder: ./cp2nas DEST|IP app1, app2, app3, ..." + return + } + $destStacks="/mnt/SSD1/docker/stacks/" + $destDir=$destStacks+$appname+"/" + Write-Host "pscp -P 22 -r ""$srcdir\*.*"" root@${destHost}:""${destDir}""" -ForegroundColor Green + Write-Host "Copying to ${destHost}:""${destStacks}" -NoNewline + Write-Host "${appname}/" -ForegroundColor DarkYellow -NoNewline + Write-Host """:" + pscp -P 22 -r "$srcdir\*.*" root@${destHost}:""${destDir}"" +} + +################################### +& $Main @Args \ No newline at end of file diff --git a/photoview/photoview_jm.txt b/photoview/photoview_jm.txt new file mode 100644 index 0000000..565bd5b --- /dev/null +++ b/photoview/photoview_jm.txt @@ -0,0 +1,132 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: photoview +Username: photovw +Disable Password: +Email: stuurmcp@telkomsa.net +UID: 3018 +Create New Primary Group: +Create Home Directory: +Samba Authentication: +Save +Credentials -> Local Groups -> Add +Name: photovw +GID: 3056 + +photovw UID: 3018 +photovw GID: 3056 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*photoview" +# create following datasets if not present +zfs create SSD1/docker/data/photoview +zfs create SSD1/docker/data/photoview/appdata +zfs create SSD1/docker/data/photoview/config +zfs create SSD1/docker/data/photoview/pgdata +zfs create SSD1/docker/data/photoview/pgbackups +chown -R photovw:photovw /mnt/SSD1/docker/data/photoview +chown -R postgres:postgres /mnt/SSD1/docker/data/photoview/pgdata +chown -R postgres:postgres /mnt/SSD1/docker/data/photoview/pgbackups + +Create folder +------------- +mkdir -p /opt/stacks/photoview/secrets + +Copy folder to docker stacks +---------------------------- +In Windows cmd shell in photoview parent (apps) folder, enter: +./cp2nas 10.0.0.20 photoview +# or +pscp -P 22 -r photoview/stacks/*.* root@10.0.0.20:/mnt/SSD1/docker/stacks/photoview/ + +Create secrets +-------------- +# NB! As of writing of this guide, I could not get photoview to work with docker secrets; steps are included to adopt docker secrets as soon as photoview supports it +# In Truenas shell: +cd /mnt/SSD1/docker/stacks/photoview/secrets +# database secrets +echo -n 'your_postgresql_database_name' > /mnt/SSD1/docker/stacks/photoview/secrets/photoview_postgresql_database +echo -n 'your_postgresql_username' > /mnt/SSD1/docker/stacks/photoview/secrets/photoview_postgresql_username +openssl rand 36 | base64 -w 0 > /mnt/SSD1/docker/stacks/photoview/secrets/photoview_postgresql_password +# for future photoview's benefit +cd /mnt/SSD1/docker/stacks/photoview/secrets/ +echo -n "postgres://$(cat photoview_postgresql_username):$(cat photoview_postgresql_password)@photoview_postgresql:5432/$(cat photoview_postgresql_database)" > photoview_database_url +# restrict access +chown -R photovw:photovw /mnt/SSD1/docker/stacks/photoview/secrets/ +chmod -R 400 /mnt/SSD1/docker/stacks/photoview/secrets/ +# read existing acl permissions, if any +getfacl /mnt/SSD1/docker/stacks/photoview/secrets +# set acl permissions +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/photoview/secrets +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/photoview/secrets/photoview_postgresql_password +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/photoview/secrets/photoview_postgresql_username +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/photoview/secrets/photoview_postgresql_database +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R +# to list secrets in secrets dir +cd /mnt/SSD1/docker/stacks/photoview/secrets +for i in $(ls -1); do echo $i = `cat $i`; done | sort + +Backup photoview database +--------------------- +In truenas shell: +mkdir /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) +chown pgadmin:pgadmin /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) + +Using browser log in to pgAdmin on truenas +Connect to servers; refer to "connecting to servers.txt", which also explains how to obtain db passwords +To perform plain text backup: +Navigate to Servers => photoview -> Databases -> photoview +Right click on photoview database and select Backup... +Enter the following on the different tabs of dialog box that opened: +General: +Replace ##### with today's date in YYYY-MM-DD format +Filename: /#####/photoview-backup.sql (this maps to: /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/#####/photoview-backup.sql on truenas) +Format: Plain +Encoding: UTF8 +Role name: photoview +Data Options: +Sections: +Pre-data: +Post-data: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Primary Group: media +Create Home Directory: +Samba Authentication: +Save + +plex UID: 3015 +media GID: 3017 + +If not done already, add mapping for media on container config +-------------------------------------------------------------- +In this example: the folder where media is stored is /mnt/stpool1/NData1/Media +On Truenas shell: +jlmkr edit docker +Add the following args to "systemd_nspawn_user_args": +--bind='/mnt/stpool1/NData1/Media:/mnt/media' + +If not done already, set ACL permissions for media to be accessible by media group +---------------------------------------------------------------------------------- +On Truenas shell: +# read and note acl entries +getfacl /mnt/stpool1/NData1 +getfacl /mnt/stpool1/NData1/Media +# set read and execute permissions for media group on parent folder +setfacl -m g:media:5 /mnt/stpool1/NData1 +# set full permissions for media group on Media folder recursively +setfacl -R -m g:media:7 /mnt/stpool1/NData1/Media +# modify defaults recursively +setfacl -R -d -m g:media:7 /mnt/stpool1/NData1/Media +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R + +set ACL permissions for custom certificates +-------------------------------------------- +# On Truenas shell: +# read and note acl entries +getfacl /mnt/SSD1/docker/data/traefik/certs +# change owner and group if not traefik +chown -R traefik:traefik /mnt/SSD1/docker/data/traefik/certs +# set access permissions to 750 +chmod -R 750 /mnt/SSD1/docker/data/traefik/certs +# modify for media group recursively +setfacl -R -m g:media:4 /mnt/SSD1/docker/data/traefik/certs +# modify defaults recursively +setfacl -R -d -m g:media:4 /mnt/SSD1/docker/data/traefik/certs + +Create datasets +--------------- +/mnt/SSD1/docker/data/plex +/mnt/SSD1/docker/data/plex/config +Set Owner:Group to plex:plex + +Copy folder to docker stacks +---------------------------- +In Windows cmd shell in plex folder, enter: +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/plex/ +This should copy compose.yaml, .env and secrets to /mnt/SSD1/docker/stacks/plex + +Create data folders +------------------- +mkdir /mnt/data/plex/config +mkdir /mnt/data/plex/transcodes +cd /mnt/data/plex + +Create secrets +-------------- +Visit https://www.plex.tv/claim/ and get your plex claim which will expire in 4 minutes +cd /opt/stacks/plex/secrets +echo -n 'claim-b6UNdeGsjjMz4tRADKfB' > plex_claim # this one is expired +chown 3015:3014 plex_claim +chmod 400 plex_claim +Update and start your plex container within the 4 minutes + +Create plex custom cert +----------------------- +openssl pkcs12 -export -out plex_cert.p12 -in plex.pem -inkey plex-key.pem -certfile plex.pem -passout stdin -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg SHA256 +# enter the password directly after executing above +# if secruity is not an issue, the password can be specified on the command line as follows: +openssl pkcs12 -export -out plex_cert.p12 -in plex.pem -inkey plex-key.pem -certfile plex.pem -passout pass:'password' -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg SHA256 + +Migrating data from old plex media server (source) to newly installed one (target) +---------------------------------------------------------------------------------- +# Stop old/source plex media server +heavyscript app --stop plex +# Stop new/target plex media server +# On Dockge, select plex and click stop +# Copy the source Library to target folder: +cp -r /mnt/stpool1/apps/plex/Library /mnt/SSD1/docker/data/plex/config/ +# Change ownership of copied folders +chown -R plex:media /mnt/stpool1/apps/plex/Library /mnt/SSD1/docker/data/plex/config/ + +Managing library files +---------------------- +Try and keep the mount folders for the media the same as that of the old media server +However, if you choose to have a different mount: +For example, +If the old media server mapped to /Media and the new one now maps to /data, then you will have to modify the media folders in plex settings to reflect the new mount. +Open plex, click on the spanner/wrench and select Manage->Libraries +Go through all the libraries items, adding new media folders and removing those that were replaced +This may take some time (depends on library size) + +Check and update custom server access URLs in Plex +-------------------------------------------------- +Open Plex web app using browser on plex server +Click on wrench/spanner, navigate to your home server name -> Settings -> Network +Scroll down to Enable Relay checkbox, and uncheck it (you can check it again after getting remote access to work) +Check entries in Custom server access URLs textbox +Update the settings to reflect new server ip address and URL; and ensure there is a URL for https://plex.sthome.org:443 +https://plex.sthome.org,http://plex.sthome.org,http://plex.sthome.org:32400 +Click on Save Changes +Still under Settings, click on Remote Access +Click on Enable Remote Access +Put check mark in Manually specify public port and enter 443 (traefik will map this to 32400) +Click on Retry +Restart plex container for good measure +Go previous Settings -> Remote Access screen +Click on Retry +The server should briefly be connected +Open Plex Windows or Android App and check if it works + +Hardware accelleration (nVidia) +------------------------------- +# install nvidia-container-toolkit; in docker shell: +curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ + && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ + sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ + sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list +apt-get update +apt-get install -y nvidia-container-toolkit +nvidia-ctk runtime configure --runtime=docker +systemctl restart docker + +Troubleshooting +--------------- +Android not connecting to server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Open plex app +Sign out from your account +Sign in entering plex account credentials +See if it works + +Transcoding: plex client fails with "An unknown error occurred (4294967283)" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + diff --git a/plex/stacks/.env b/plex/stacks/.env new file mode 100644 index 0000000..28a4e50 --- /dev/null +++ b/plex/stacks/.env @@ -0,0 +1,19 @@ +############################################################################################## +# Values to be used for substitution by docker compose in compose.yml AND .*.env files +############################################################################################## + +APPLICATION_NAME=plex + +DOCKERDIR=/mnt/SSD1/docker +MEDIADIR=/mnt/stpool1/NData1/Media + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +SERVICE_PORT=32400 +DOMAINNAME=sthome.org + + diff --git a/plex/stacks/.plex.env b/plex/stacks/.plex.env new file mode 100644 index 0000000..cf814a8 --- /dev/null +++ b/plex/stacks/.plex.env @@ -0,0 +1,33 @@ + +############################################################################################## +# Environment variables for plex +############################################################################################## + +PUID=3015 +PGID=3017 +PLEX_UID=3015 +PLEX_GID=3017 +TZ=Africa/Johannesburg + +ADVERTISE_IP=https://plex.sthome.org + +LOCAL_IPS=127.0.0.1/32,10.0.0.0/20,192.168.2.0/24,10.255.224.0/20 + +# Valid settings for VERSION are:- +# docker: Let Docker handle the Plex Version, we keep our Dockerhub Endpoint up to date with the latest public builds. This is the same as leaving this setting out of your create command. +# latest: will update plex to the latest version available that you are entitled to. +# public: will update plexpass users to the latest public version, useful for plexpass users that don't want to be on the bleeding edge but still want the latest public updates. +# : will select a specific version (eg 0.9.12.4.1192-9a47d21) of plex to install, note you cannot use this to access plexpass versions if you do not have plexpass. +VERSION=docker + + +# set to: all or UUID / to get UUID use nvidia-smi --query-gpu=gpu_name,gpu_uuid --format=csv +NVIDIA_VISIBLE_DEVICES=all # "GPU-b9bf37c1-f8c9-201c-3456-0aa35381be42" + + +# Visit https://www.plex.tv/claim/ and get your plex claim which will expire in 4 minutes +# save in plex_claim file in SECRETSDIR and start plex media server app before expiration period ends +PLEX_CLAIM=file:///run/secrets/plex_claim + + + diff --git a/plex/stacks/compose.yml b/plex/stacks/compose.yml new file mode 100644 index 0000000..51ac776 --- /dev/null +++ b/plex/stacks/compose.yml @@ -0,0 +1,99 @@ +# See .static-ips.yml for static ip addresses + +name: plex + +networks: + traefik-net: + external: true + +secrets: + plex_claim: + file: ${SECRETSDIR}/plex_claim + +services: + plex: + image: lscr.io/linuxserver/plex:latest + restart: unless-stopped + env_file: .plex.env + hostname: plex + secrets: + - plex_claim + # this deploy section requires the installation of the nvidia-container-toolkit; comment out if the toolkit is not installed + deploy: + resources: + reservations: + devices: + - driver: nvidia + #count: 1 + device_ids: + - "GPU-b9bf37c1-f8c9-201c-3456-0aa35381be42" + capabilities: [gpu] + volumes: + - "${DATADIR}/config:/config" + - "${DATADIR}/transcodes:/transcode" + - "${CERTSDIR}:/certs" + - "${MEDIADIR}:/data" + networks: + - traefik-net +# Set plex network custom server access URLs setting to: https://plex.sthome.org,http://plex.sthome.org,http://plex.sthome.org:32400,http://10.0.0.61:32400 +# Enable hairpin / NAT Loopback at NAT setting for plex on router +# Use ipaddr:32400 for WebUI access (insecure) / perform ipconfig /flushdns and restart browser + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # tcp service + # ----------- + - "traefik.tcp.services.${APPLICATION_NAME}-tcp-svc.loadbalancer.server.port=${SERVICE_PORT}" + # + # http service + # ------------ + - "traefik.http.services.${APPLICATION_NAME}-http-svc.loadbalancer.server.port=${SERVICE_PORT}" + # + # tcp routers + # ----------- + # limit router to plex ":32400" entrypoint + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-rtr.entrypoints=plex" + # set match criteria for router, since this is not tls, header might not contain hostsni field; we're forced to use wildcard + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-rtr.rule=HostSNI(`*`)" + # assign svc target to router + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-rtr.service=${APPLICATION_NAME}-tcp-svc" + # + # limit router to plex ":32400" entrypoint + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.entrypoints=plex" + # set match criteria for router + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.rule=HostSNI(`${APPLICATION_NAME}.${DOMAINNAME}`)" + # set router to be dedicated to secure requests only for the hosts specified in match criteria + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls=true" + # forward requests "as is" keeping all data encrypted. + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls.passthrough=true" + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls.options=tls-options@file" + # generate certificates using following certresolver + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.tls.certresolver=solver-dns" + # assign svc target to router + - "traefik.tcp.routers.${APPLICATION_NAME}-tcp-secure-rtr.service=${APPLICATION_NAME}-tcp-svc" + # + # http routers + # ------------ + # limit router to web ":80" and plex ":32400" entrypoints + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=plex, web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach secure headers middlewares + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-redirect@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-http-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders@file" + # set router to be dedicated to secure requests only for the hosts specified in match criteria + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-http-svc" diff --git a/prometheus/cp2nas.ps1 b/prometheus/cp2nas.ps1 new file mode 100644 index 0000000..6778989 --- /dev/null +++ b/prometheus/cp2nas.ps1 @@ -0,0 +1,57 @@ +############### MAIN ############### +$Main = +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + [Parameter(Mandatory=$false)] + [string[]] $apps + ) + If($PSBoundParameters.ContainsKey("apps")) { + foreach ($appname in $apps) + { + copyfolder $destHost "$appname\stacks" $appname + } + } + else { + $appname="$pwd".Split("\\")[-1] + copyfolder $destHost "stacks" $appname + } +} + +################################### +Function copyfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $appname + ) + if (-Not(Test-Path -Path $srcdir)) { + Write-Host "Source path doesn't exist: ""$PSScriptRoot\$srcdir\*.*"". No files copied!" -ForegroundColor Red + Write-Host "Usage: in app folder : ./cp2nas DEST|IP" + Write-Host " in app parent folder: ./cp2nas DEST|IP app1, app2, app3, ..." + return + } + $destStacks="/mnt/SSD1/docker/stacks/" + $destDir=$destStacks+$appname+"/" + Write-Host "pscp -P 22 -r ""$srcdir\*.*"" root@${destHost}:""${destDir}""" -ForegroundColor Green + Write-Host "Copying to ${destHost}:""${destStacks}" -NoNewline + Write-Host "${appname}/" -ForegroundColor DarkYellow -NoNewline + Write-Host """:" + pscp -P 22 -r "$srcdir\*.*" root@${destHost}:""${destDir}"" +} + +################################### +& $Main @Args \ No newline at end of file diff --git a/prometheus/data/config/prometheus.yml b/prometheus/data/config/prometheus.yml new file mode 100644 index 0000000..0612bba --- /dev/null +++ b/prometheus/data/config/prometheus.yml @@ -0,0 +1,65 @@ +global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s + +alerting: + alertmanagers: + - static_configs: + - targets: + - alert-manager:9093 + scheme: http + timeout: 10s + api_version: v2 + +scrape_configs: + +# grafana dashboard id: 159 + - job_name: prometheus + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - prometheus:9090 + +# wg-easy current production version does not support metrics (2024/12) +## grafana dashboard id: 21733 +# - job_name: wg-easy +## #basic_auth: +### # username: wgpw +### # password: +### # password_file: +### scheme: http +### static_configs: +## - targets: +# - wg-easy:51821 + +# grafana dashboard id: 17346 + - job_name: traefik + #scheme: https + static_configs: + - targets: + - traefik:8082 + +# grafana dashboard id: 14282 + - job_name: cadvisor + scrape_interval: 300s + scrape_timeout: 55s + static_configs: + - targets: + - cadvisor:8080 + +# grafana dashboard id: 1860 + - job_name: node + static_configs: + - targets: + - node-exporter:9100 + +# grafana dashboard id: 18226 + - job_name: frigate + static_configs: + - targets: + - frigate-exporter:9200 diff --git a/prometheus/data/config/rules.yml b/prometheus/data/config/rules.yml new file mode 100644 index 0000000..81e4c0e --- /dev/null +++ b/prometheus/data/config/rules.yml @@ -0,0 +1,6 @@ +groups: + - name: example + rules: + - alert: InstanceDown + expr: up == 0 + for: 1m \ No newline at end of file diff --git a/prometheus/prometheus_jm.txt b/prometheus/prometheus_jm.txt new file mode 100644 index 0000000..7e1b636 --- /dev/null +++ b/prometheus/prometheus_jm.txt @@ -0,0 +1,77 @@ +# https://mxulises.medium.com/simple-prometheus-setup-on-docker-compose-f702d5f98579 + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: prometheus +Username: prometh +Disable Password: +Email: +UID: 3021 +Create New Primary Group: +Create Home Directory: +Samba Authentication: +Save +Check Credentials -> Local Groups for GID +Name: prometh +GID: 3020 + +prometh UID: 3021 +prometh GID: 3020 + +Create datasets +--------------- +/mnt/SSD1/docker/data/prometheus ; set Owner:Group to prometheus:prometheus +/mnt/SSD1/docker/data/prometheus/config ; set Owner:Group to prometheus:prometheus +/mnt/SSD1/docker/data/prometheus/appdata ; set Owner:Group to prometheus:prometheus +/mnt/SSD1/docker/data/prometheus/alertmgr ; set Owner:Group to prometheus:prometheus + +Create folder +------------- +mkdir /mnt/SSD1/docker/stacks/prometheus + +Create secrets +-------------- +# In docker shell: +cd /opt/stacks/prometheus/secrets +# generate password hash and convert $ in hash to $$; password must be surrounded by single quotes +echo $(htpasswd -nB admin) +# Remove the single quotes from the generated hash and copy the result to local stacks\.env file +# Repeat the above for the prometheus metrics password + +Creating user password hash strings for user authorisation using traefik basic-auth +----------------------------------------------------------------------------------- +# If not installed, install htpasswd: +jlmkr shell docker +apt update & apt install apache2-utils +# The user credentials can be applied as a label entry in the compose.yml file or as a line entry in a text file +# When used as a label entry, all '$' needs to be escaped with a second '$'; sed can be used for this purpose: +# To create user list textfile line item +echo $(htpasswd -nB admin) +# To create string to be used in compose file label +echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g +# See traefik_jm.txt for more detailed instructions + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in prometheus folder, enter: +./cp2nas 10.0.0.20 +# OR +pscp -P 22 -r stacks/*.* root@10.0.0.20:/mnt/SSD1/docker/stacks/prometheus/ +# The above should copy compose.yaml and .env to /mnt/SSD1/docker/stacks/prometheus + +Prometheus exporters +-------------------- +https://github.com/bairhys/prometheus-frigate-exporter + +Troubleshooting +--------------- +Config file +~~~~~~~~~~~ +# Check for errors in config file with the following command: +docker exec prometheus-prometheus-1 promtool check config /etc/prometheus/prometheus.yml +# note that "prometheus-prometheus-1" is the prometheus container name + +Endpoints +~~~~~~~~~ +# Open "https://prometheus.sthome.org/targets" in browser to check whether endpoints are up diff --git a/prometheus/stacks/.env b/prometheus/stacks/.env new file mode 100644 index 0000000..671e1af --- /dev/null +++ b/prometheus/stacks/.env @@ -0,0 +1,20 @@ +################################################################ +APPLICATION_NAME=prometheus + +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +PUID=3021 +PGID=3020 +DOMAINNAME=sthome.org + +################################################################ + +WEBUI_PORT=9090 + + diff --git a/prometheus/stacks/alertmanager/alertmanager.yml b/prometheus/stacks/alertmanager/alertmanager.yml new file mode 100644 index 0000000..d6ca599 --- /dev/null +++ b/prometheus/stacks/alertmanager/alertmanager.yml @@ -0,0 +1,19 @@ +global: + smtp_smarthost: 'smtp.telkomsa.net:25' + smtp_from: 'alertmanager@sthome.org' + smtp_auth_username: 'stuurman30@telkomsa.net' + smtp_auth_password: "UltraM3!2024#" + +route: + receiver: 'mail' + repeat_interval: 4h + group_by: [alertname] + +receivers: + - name: 'mail' + email_configs: + - smarthost: 'smtp.telkomsa.net:25' + auth_username: 'stuurman30@telkomsa.net' + auth_password: "UltraM3!2024#" + from: 'alertmanager@sthome.org' + to: 'stuurmcp@telkomsa.net' \ No newline at end of file diff --git a/prometheus/stacks/compose.yml b/prometheus/stacks/compose.yml new file mode 100644 index 0000000..d29d80f --- /dev/null +++ b/prometheus/stacks/compose.yml @@ -0,0 +1,134 @@ + +name: prometheus + +secrets: + prometheus_metrics_password: + file: ${STACKSDIR}/secrets/prometheus_metrics_password + +networks: + backend: + name: prometheus-net + driver: bridge + ipam: + config: + - subnet: 10.255.223.0/27 # Range: 10.255.223.1 - 10.255.223.30 + driver_opts: + com.docker.network.bridge.name: "br-prometheus" + internal: true + + traefik-net: + external: true + +services: + prometheus: + image: prom/prometheus:latest #v2.54.1 + command: + - '--config.file=/etc/prometheus/prometheus.yml' + networks: + - traefik-net + - backend + restart: unless-stopped + user: "${PUID}:${PGID}" + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/config:/etc/prometheus" + - "${DATADIR}/appdata:/prometheus" + secrets: + - prometheus_metrics_password + environment: + - PROMETHEUS_METRICS_PASSWORD + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http service + # ------------ + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http middlewares + # ---------------- + - "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/${APPLICATION_NAME}.txt" + # + # http routers + # ------------ + # http://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # https://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + # https://appname.domainname/-/healthy (for status check) + - "traefik.http.routers.${APPLICATION_NAME}-secure-status-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-status-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/-/healthy`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-status-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-status-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-status-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-status-rtr.tls.certresolver=solver-dns" + - "traefik.http.routers.${APPLICATION_NAME}-secure-status-rtr.service=${APPLICATION_NAME}-svc" + + node-exporter: + image: prom/node-exporter:v1.8.2 + hostname: node-exporter + networks: + - backend + ports: + - 9100:9100 + restart: unless-stopped + + alert-manager: + image: prom/alertmanager:v0.27.0 + command: --config.file=/config/alertmanager.yml # --log.level=debug + volumes: + - "${STACKSDIR}/alertmanager:/config" + - "${DATADIR}/alertmgr:/data" + networks: + - backend + ports: + - 9093:9093 + restart: unless-stopped + +# to enable profiling of cadvisor +# https://github.com/google/cadvisor/issues/2523 +# iwankgb +# add argument -profiling to your cadvisor invocation and navigate to IP:PORT/debug/pprof/profile?seconds=300. It will generate profile for 300 seconds of cAdvisor execution. After 300 seconds a file will be sent to you - download it and then navigate to the directory where the file is saved and execute: go tool pprof profile (profile is default name for the downloaded file). It will open profiling console. Type web and hit enter. After some time a browser should be opened on your system and you should execution profile for your instance. +# http://docker.sthome.org:8080/debug/pprof/profile?seconds=300 to get results + cadvisor: + image: gcr.io/cadvisor/cadvisor:v0.49.1 +# command: -profiling # setting for profiling cadvisor + volumes: + - /:/rootfs:ro + - /var/run:/var/run:ro + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /dev/disk/:/dev/disk:ro + privileged: true + devices: + - /dev/kmsg + networks: + - backend +# - traefik-net # setting for profiling cadvisor + ports: + - 8080:8080 + restart: unless-stopped + + frigate-exporter: + image: rhysbailey/prometheus-frigate-exporter + hostname: frigate-exporter + restart: unless-stopped + networks: + - traefik-net # to reach frigate externally + - backend + ports: + - 10.255.223.1:9200:9200 # restrict the port to backend network + environment: + - PORT=9200 + - FRIGATE_STATS_URL=http://10.0.0.51:5000/api/stats diff --git a/prometheus/traefik-users/prometheus.txt b/prometheus/traefik-users/prometheus.txt new file mode 100644 index 0000000..a5462c1 --- /dev/null +++ b/prometheus/traefik-users/prometheus.txt @@ -0,0 +1,4 @@ +grafana:$2y$05$r6bSihiBh.xKWV5FPP9yPunhIr0t.cavZqq2Ghsl6TEGKbXDXk6qy +admin:$2y$05$djOyLnsk5p1.wcCLJCXpcehznR3cc04otaSlpED3fSRC9EpRGDkMC +chris:$2y$05$FSl7QIqo.VMe69nm8K.Dv.O05Gi6oad.2qY7oKjgqbPa4eBPintbK +Chris:$2y$05$8r6M8zr0MFIiDLUm1vP1Ee0AP8kMJtDsw4zezFeSDVlWeEOkwuBuC \ No newline at end of file diff --git a/root/root_jm.txt b/root/root_jm.txt new file mode 100644 index 0000000..01ef803 --- /dev/null +++ b/root/root_jm.txt @@ -0,0 +1,133 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: rootappapp +Username: rootappapp +Disable Password: +Email: +UID: (note) +Create New Primary Group: +Email: +UID: (note) +Create New Primary Group: +Primary Group: sheetabl +Create Home Directory: +Samba Authentication: +Save + +sheetabl UID: 3051 +sheetabl GID: 3050 + +Create datasets +--------------- +/mnt/SSD1/docker/data/sheetable # set Owner:Group to sheetabl:sheetabl +/mnt/SSD1/docker/data/sheetable/config # set Owner:Group to sheetabl:sheetabl +/mnt/SSD1/docker/data/sheetable/pgbackups # set Owner:Group to pguser:pguser +/mnt/SSD1/docker/data/sheetable/pgdata # set Owner:Group to pguser:pguser + +Create secrets folder +--------------------- +mkdir -p /opt/stacks/sheetable/secrets + +Verifying truenas sheetable container sheets folder +--------------------------------------------------- +# List sheetable pods to check if they are running and to get pod name. If not, wait for the container to start: +k3s kubectl get pods -n ix-sheetable +# If all are ok, the listed containers should resemble the following: +# NAME READY STATUS RESTARTS AGE +# sheetable-cnpg-main-1 1/1 Running 0 5d23h +# sheetable-66df7b74c5-qr9jq 1/1 Running 0 12m +# Verify that the /app/config folder has a sheets subfolder: +k3s kubectl exec -n ix-sheetable sheetable-66df7b74c5-qr9jq -c sheetable -it -- ls -al /app/config +# expected listing: +# total 2 +# drwxr-xr-x 3 568 568 3 Jul 11 16:33 . +# drwxr-xr-x 1 root root 3 Sep 21 11:58 .. +# drwxr-xr-x 4 568 568 4 Jul 11 16:33 sheets +# If you don't see the sheets folder as per the above, shell into the container and check where the sheets folder is located. +k3s kubectl exec -n ix-sheetable sheetable-66df7b74c5-qr9jq -c sheetable -it -- sh + +# Update the APPLICATION_CONFIG_PATH value in the .env file with the correct location if not /app/config + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in sheetable folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/sheetable/ +# This should copy sheetable stacks folder to /mnt/SSD1/docker/stacks/sheetable + +Create secrets +-------------- +# In Truenas shell: +cd /mnt/SSD1/docker/stacks/sheetable/secrets +echo -n 'your_admin_email' > /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_admin_email +echo -n 'your_admin_password' > /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_admin_password +echo -n 'your_db_name' > /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_postgresql_database +echo -n 'your_db_user' > /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_postgresql_username +openssl rand 36 | base64 -w 0 > /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_postgresql_password +openssl rand 26 | base64 -w 0 | sed 's/[\$,\#,/,+,=]//g' > /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_api_secret +# restrict access +cd /mnt/SSD1/docker/stacks/sheetable +chown -R sheetabl:sheetabl secrets/ +chmod -R 400 secrets/ +# read existing acl permissions, if any +getfacl /mnt/SSD1/docker/stacks/sheetable/secrets +# set acl permissions +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/sheetable/secrets +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_postgresql_password +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_postgresql_username +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/sheetable/secrets/sheetable_postgresql_database +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R +# to list secrets in secrets dir +cd /mnt/SSD1/docker/stacks/authentik/secrets +for i in $(ls -1); do echo $i = `cat $i`; done | sort + + +Backup sheetable database +-------------------------- +# In truenas shell: +mkdir /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) +chown pgadmin:pgadmin /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/$(date -I) +# Using browser, log in to pgAdmin on truenas +# Connect to servers; refer to "connecting to servers.txt", which also explains how to obtain db passwords +# To perform plain text backup: +# Navigate to Servers => sheetable -> Databases -> sheetable +# Right click on sheetable database and select Backup... +# Enter the following on the different tabs of dialog box that opened: +General: +# Replace ##### with date in YYYY-MM-DD format when backup is being made +Filename: /#####/sheetable-backup.sql (this maps to: /mnt/stpool1/apps/pgadmin/storage/stuurmcp_telkomsa.net/#####/sheetable-backup.sql on truenas) +# Or click on folder icon and navigate to the folder that was created above. Enter sheetable-backup.sql in Save As field, then click on Create +Format: Plain +Encoding: UTF8 +Role name: sheetable +Data Options: +Sections: +Pre-data: +Post-data: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Primary Group: swebsvr +Create Home Directory: +Samba Authentication: +Save + +swebsvr UID: 3053 +swebsvr GID: 3052 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*static-web-server" +# create following datasets if not present +zfs create SSD1/docker/data/static-web-server +zfs create SSD1/docker/data/static-web-server/appdata +zfs create SSD1/docker/data/static-web-server/config +chown -R swebsvr:swebsvr /mnt/SSD1/docker/data/static-web-server + +Create folders +-------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/static-web-server + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in static-web-server folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/static-web-server/ +# This should copy static-web-server stacks folder to /mnt/SSD1/docker/stacks/static-web-server + +Migrating data +-------------- +# Stop static-web-server on truenas, in truenas shell +heavyscript app --stop static-web-server +# copy config storage to new install data folder +cp -pr /mnt/stpool1/apps/static-web-server/* /mnt/SSD1/docker/data/static-web-server/config/ +cp -pr /mnt/stpool1/appdata/static-web-server/* /mnt/SSD1/docker/data/static-web-server/appdata/ +chown -R swebsvr:swebsvr /mnt/SSD1/docker/data/static-web-server/ + + diff --git a/syncthing/stacks/.env b/syncthing/stacks/.env new file mode 100644 index 0000000..833f695 --- /dev/null +++ b/syncthing/stacks/.env @@ -0,0 +1,29 @@ + +APPLICATION_NAME=syncthing + +DOCKERDIR=/mnt/SSD1/docker/ +MEDIADIR=/mnt/stpool1/NData1/Media +DOWNLOADSDIR=/mnt/stpool1/Downloads + +STAGINGDIR=/mnt/stpool1/NData1/staging +SHAREDDATADIR=/mnt/stpool1/Shared_Data +BULKSTOREDIR=/mnt/stpool1/NData2/bulkstore +SYNCHEDDIR=/mnt/stpool1/synched +OBJECTSTOREDIR=/mnt/stpool1/objectstore + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +PUID=3054 +PGID=3053 +MEDIA_PGID=3017 + +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org +WEBUI_PORT=8384 + +# refer to .static-ips.yml for the IP address of the container +SYNCTHING_IP=192.168.2.241 diff --git a/syncthing/stacks/.syncthing.env b/syncthing/stacks/.syncthing.env new file mode 100644 index 0000000..f831b12 --- /dev/null +++ b/syncthing/stacks/.syncthing.env @@ -0,0 +1,6 @@ + +PUID=${PUID} +PGID=${MEDIA_PGID} +TZ=${TZ} +UMASK=0002 + diff --git a/syncthing/stacks/compose.yml b/syncthing/stacks/compose.yml new file mode 100644 index 0000000..56a3a93 --- /dev/null +++ b/syncthing/stacks/compose.yml @@ -0,0 +1,60 @@ + +name: syncthing + +networks: + traefik-net: + external: true + macvlan0: + external: true +services: + syncthing: + image: lscr.io/linuxserver/syncthing:latest + hostname: "${APPLICATION_NAME}" + networks: + traefik-net: null + macvlan0: + ipv4_address: "${SYNCTHING_IP}" + + env_file: .syncthing.env + volumes: + - "${DATADIR}/config:/config" + - "${SYNCHEDDIR}:/synched" + - "${MEDIADIR}:/mnt/media" + restart: unless-stopped + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # http middlewares + # --------------------------- + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.users=${ADMIN_CREDENTIALS}, ${USER_CREDENTIALS}" + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/${APPLICATION_NAME}.txt" + # + # http services + # ------------- + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http routers + # ------------ + # limit router to web ":80" entrypoint (Note: web entrypoint http requests are globally redirected to websecure router in traefik.yml) + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # + # limit router to websecure ":443" entrypoint + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + # set match criteria for router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + # set router to be dedicated to secure requests only for the host specified in match criteria + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + # assign tls-options + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + # generate certificates using following certresolver + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # attach middlewares to routers + #- "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + # assign svc target to routers + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" diff --git a/syncthing/syncthing_jm.txt b/syncthing/syncthing_jm.txt new file mode 100644 index 0000000..b69d78a --- /dev/null +++ b/syncthing/syncthing_jm.txt @@ -0,0 +1,81 @@ +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: syncthing +Username: syncthin +Disable Password: +Email: stuurmcp@telkomsa.net +UID: (note) +Create New Primary Group: +Primary Group: tautulli +Create Home Directory: +Samba Authentication: +Save + +tautulli UID: 3055 +tautulli GID: 3054 + +Create datasets +--------------- +/mnt/SSD1/docker/data/tautulli +/mnt/SSD1/docker/data/tautulli/config +# Set Owner:Group to tautulli:tautulli + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in tautulli folder, enter: +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/tautulli/ +# This should copy compose.yaml, .env and secrets to /mnt/SSD1/docker/stacks/tautulli + +Create folders +-------------- +mkdir /opt/stacks/tautulli + +Migrating data from old tautulli to newly installed one (target) +---------------------------------------------------------------- +# Stop old/source tautulli media server +heavyscript app --stop tautulli + +# Stop new/target tautulli media server +# On Dockge, select tautulli and click stop +# Copy the source Library to target folder: +cp -pr /mnt/stpool1/apps/tautulli/* /mnt/SSD1/docker/data/tautulli/config/ + +Check and update custom server access URLs in tautulli +------------------------------------------------------ +# Open tautulli web app using browser +# Go to Setting -> Plex Media Server +# Change Plex IP Address or Hostname field to "plex". This is assuming that tautulli and plex is on the same docker network. + + + + + diff --git a/traefik/app-wg-easy.yml b/traefik/app-wg-easy.yml new file mode 100644 index 0000000..762e171 --- /dev/null +++ b/traefik/app-wg-easy.yml @@ -0,0 +1,14 @@ +entryPoints: + wgudpep: + address: ':51820/udp' +udp: + routers: + wg-rtr: + entryPoints: + - wgudpep + service: wg-svc + services: + wg-svc: + loadBalancer: + servers: + - address: 'wg-easy:51820' \ No newline at end of file diff --git a/traefik/cp2nas.ps1 b/traefik/cp2nas.ps1 new file mode 100644 index 0000000..6778989 --- /dev/null +++ b/traefik/cp2nas.ps1 @@ -0,0 +1,57 @@ +############### MAIN ############### +$Main = +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + [Parameter(Mandatory=$false)] + [string[]] $apps + ) + If($PSBoundParameters.ContainsKey("apps")) { + foreach ($appname in $apps) + { + copyfolder $destHost "$appname\stacks" $appname + } + } + else { + $appname="$pwd".Split("\\")[-1] + copyfolder $destHost "stacks" $appname + } +} + +################################### +Function copyfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $appname + ) + if (-Not(Test-Path -Path $srcdir)) { + Write-Host "Source path doesn't exist: ""$PSScriptRoot\$srcdir\*.*"". No files copied!" -ForegroundColor Red + Write-Host "Usage: in app folder : ./cp2nas DEST|IP" + Write-Host " in app parent folder: ./cp2nas DEST|IP app1, app2, app3, ..." + return + } + $destStacks="/mnt/SSD1/docker/stacks/" + $destDir=$destStacks+$appname+"/" + Write-Host "pscp -P 22 -r ""$srcdir\*.*"" root@${destHost}:""${destDir}""" -ForegroundColor Green + Write-Host "Copying to ${destHost}:""${destStacks}" -NoNewline + Write-Host "${appname}/" -ForegroundColor DarkYellow -NoNewline + Write-Host """:" + pscp -P 22 -r "$srcdir\*.*" root@${destHost}:""${destDir}"" +} + +################################### +& $Main @Args \ No newline at end of file diff --git a/traefik/data/haproxy/haproxy.cfg.template b/traefik/data/haproxy/haproxy.cfg.template new file mode 100644 index 0000000..f019ded --- /dev/null +++ b/traefik/data/haproxy/haproxy.cfg.template @@ -0,0 +1,78 @@ +global + log stdout format raw daemon "${LOG_LEVEL}" + + pidfile /run/haproxy.pid + maxconn 4000 + + # Turn on stats unix socket + server-state-file /var/lib/haproxy/server-state + +defaults + mode http + log global + option httplog + option dontlognull + option http-server-close + option redispatch + retries 3 + timeout http-request 10s + timeout queue 1m + timeout connect 10s + timeout client 10m + timeout server 10m + timeout http-keep-alive 10s + timeout check 10s + maxconn 3000 + + # Allow seamless reloads + load-server-state-from-file global + + # Use provided example error pages + errorfile 400 /usr/local/etc/haproxy/errors/400.http + errorfile 403 /usr/local/etc/haproxy/errors/403.http + errorfile 408 /usr/local/etc/haproxy/errors/408.http + errorfile 500 /usr/local/etc/haproxy/errors/500.http + errorfile 502 /usr/local/etc/haproxy/errors/502.http + errorfile 503 /usr/local/etc/haproxy/errors/503.http + errorfile 504 /usr/local/etc/haproxy/errors/504.http + +backend dockerbackend + server dockersocket $SOCKET_PATH + +backend docker-events + server dockersocket $SOCKET_PATH + timeout server 5m + +frontend dockerfrontend + bind ${BIND_CONFIG} + http-request deny unless METH_GET || { env(POST) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/((stop)|(restart)|(kill)) } { env(ALLOW_RESTARTS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/start } { env(ALLOW_START) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/[a-zA-Z0-9_.-]+/stop } { env(ALLOW_STOP) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/auth } { env(AUTH) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/build } { env(BUILD) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/commit } { env(COMMIT) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/configs } { env(CONFIGS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers } { env(CONTAINERS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/distribution } { env(DISTRIBUTION) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/events } { env(EVENTS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/exec } { env(EXEC) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/grpc } { env(GRPC) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/images } { env(IMAGES) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/info } { env(INFO) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/networks } { env(NETWORKS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/nodes } { env(NODES) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/_ping } { env(PING) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/plugins } { env(PLUGINS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/secrets } { env(SECRETS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/services } { env(SERVICES) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/session } { env(SESSION) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/swarm } { env(SWARM) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/system } { env(SYSTEM) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/tasks } { env(TASKS) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/version } { env(VERSION) -m bool } + http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/volumes } { env(VOLUMES) -m bool } + http-request deny + default_backend dockerbackend + + use_backend docker-events if { path,url_dec -m reg -i ^(/v[\d\.]+)?/events } diff --git a/traefik/stacks/.env b/traefik/stacks/.env new file mode 100644 index 0000000..d431bdf --- /dev/null +++ b/traefik/stacks/.env @@ -0,0 +1,20 @@ +################################################################ +# .env +# When both env_file and environment are set for a service, values set by environment have precedence. +# https://docs.docker.com/compose/environment-variables/envvars-precedence/ +# +# +################################################################ + +APPLICATION_NAME=traefik +DOCKERDIR=/mnt/SSD1/docker/ +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATADIR=${DOCKERDIR}/data/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +DOMAINNAME=sthome.org + +PUID=3012 +PGID=3011 +TZ=Africa/Johannesburg + diff --git a/traefik/stacks/.socket-proxy.env b/traefik/stacks/.socket-proxy.env new file mode 100644 index 0000000..97691c1 --- /dev/null +++ b/traefik/stacks/.socket-proxy.env @@ -0,0 +1,36 @@ +# +# environment variables for socket-proxy +# + +LOG_LEVEL=info # debug,info,notice,warning,err,crit,alert,emerg + +## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.). +### 0 to revoke access. +### 1 to grant access. +## Granted by Default +EVENTS=1 +PING=1 +VERSION=1 +## Revoked by Default +### Security critical +AUTH=0 +SECRETS=0 +POST=1 # Watchtower +### Not always needed +BUILD=0 +COMMIT=0 +CONFIGS=0 +CONTAINERS=1 # Traefik, portainer, etc. +DISTRIBUTION=0 +EXEC=0 +IMAGES=1 # Portainer +INFO=1 # Portainer +NETWORKS=1 # Portainer +NODES=0 +PLUGINS=0 +SERVICES=1 # Portainer +SESSION=0 +SWARM=0 +SYSTEM=0 +TASKS=1 # Portainer +VOLUMES=1 # Portainer \ No newline at end of file diff --git a/traefik/stacks/.traefik.env b/traefik/stacks/.traefik.env new file mode 100644 index 0000000..b6490a6 --- /dev/null +++ b/traefik/stacks/.traefik.env @@ -0,0 +1,15 @@ +# +# environment variables for traefik +# + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +################################################################ +#################### Traefik 3 - June 2024 ##################### +# Cloudflare IPs (IPv4 and/or IPv6): https://www.cloudflare.com/ips/ +################################################################ +CLOUDFLARE_IPS=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22 +LOCAL_IPS=127.0.0.1/32,10.0.0.0/24,192.168.2.0/24,172.16.0.0/12,10.255.224.0/20 +CF_DNS_API_TOKEN_FILE=/run/secrets/cf_dns_api_token \ No newline at end of file diff --git a/traefik/stacks/compose.yml b/traefik/stacks/compose.yml new file mode 100644 index 0000000..941b50a --- /dev/null +++ b/traefik/stacks/compose.yml @@ -0,0 +1,206 @@ + +name: traefik + +############################################################### +# Networks +############################################################### +networks: + socket_proxy: + driver: bridge + driver_opts: + com.docker.network.bridge.name: "br-traefik_sx" + traefik-net: + external: true + mariadb-net: + external: true + +############################################################### +# Docker Secrets +# Owner (default): root:root +# Recommend Set Owner to match container user Example: UID=1100, GID=1100 +# Permissions of files & directory on host to: 0400 (-r--) +############################################################### +secrets: + ## Cloudflare / Traefik + cf_dns_api_token: + file: ${SECRETSDIR}/cf_dns_api_token + +############################################################### + +services: + traefik: + image: traefik:v3.3.3 # v3.2.1 # v3.1.7 # 3.1.2 # v3.1.7-nanoserver-ltsc2022 + hostname: traefik + restart: unless-stopped + env_file: .traefik.env + security_opt: + - no-new-privileges=true + depends_on: + - socket-proxy # Comment out if not using socket-proxy + networks: + - traefik-net + - socket_proxy + - mariadb-net + command: + - "--configFile=/config/traefik.yml" + ports: + - target: 80 # Container Port + host_ip: 0.0.0.0 # All interfaces, not a specific one + published: "80" # STRING + protocol: tcp # tcp or udp + mode: host # or Ingress for load balancing + - target: 443 + host_ip: 0.0.0.0 + published: "443" + protocol: tcp + mode: host + - target: 51820 # wg-easy udp port + published: "51820" + protocol: udp + mode: host + - target: 32400 # plex remote access tcp port + published: "32400" + protocol: tcp + mode: host + - target: 1883 # mosquitto port + published: "1883" + protocol: tcp + mode: host + - target: 8883 # mosquitto secure port + published: "8883" + protocol: tcp + mode: host + - target: 19132 # minecraft-bedrock port + published: "19132" + protocol: udp + mode: host + - target: 25565 # minecraft-java port + published: "25565" + protocol: udp + mode: host + - target: 25575 # minecraft-java rcon port + published: "25575" + protocol: tcp + mode: host + - target: 8083 # ping port + published: "8083" + protocol: tcp + mode: host + - target: 8306 # mariadb port + published: "8306" + protocol: tcp + mode: host + - target: 9306 # mysql port + published: "9306" + protocol: tcp + mode: host + - target: 2022 # sftp port1 + published: "2022" + protocol: tcp + mode: host + - target: 2023 # sftp port2 + published: "2023" + protocol: tcp + mode: host + - target: 2024 # sftp port3 + published: "2024" + protocol: tcp + mode: host + - target: 2025 # sftp port4 + published: "2025" + protocol: tcp + mode: host + - target: 2026 # sftp port5 + published: "2026" + protocol: tcp + mode: host + - target: 2027 # sftp port6 + published: "2027" + protocol: tcp + mode: host + - target: 2028 # sftp port7 + published: "2028" + protocol: tcp + mode: host + - target: 2029 # sftp port8 + published: "2029" + protocol: tcp + mode: host + secrets: + - cf_dns_api_token + volumes: + - "$STACKSDIR/config:/config" # traefik.yml + - "$STACKSDIR/rules:/rules" # Dynamic File Provider directory + - "$STACKSDIR/users:/mnt/users" # basic-auth username and password hashes + - "$DATADIR/appdata:/data" # acme.json defined in traefik.yaml + - "$DATADIR/logs:/logs" + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http basic-auth middlewares + # --------------------------- + - "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/${APPLICATION_NAME}.txt" + # + # http routers + # ------------ + # http + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`traefik.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=${APPLICATION_NAME}-auth, http-mw-rateLimit-secureHeaders-compress-redirect@file" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=api@internal" + + # https + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`traefik.${DOMAINNAME}`)&& PathPrefix(`/`)" + # attach middlewares to routers + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth, http-mw-rateLimit-secureHeaders-compress@file" + # tls + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # assign svc target to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=api@internal" + +############################################################### + socket-proxy: + image: tecnativa/docker-socket-proxy:0.2.0 #0.1.2 + hostname: traefik_socket-proxy + restart: unless-stopped + env_file: .socket-proxy.env + security_opt: + - no-new-privileges=true + networks: + - socket_proxy + privileged: true # true for VM. false for unprivileged LXC container. + #depends_on: + # - traefik + ports: + - "127.0.0.1:2375:2375" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + # the following bind is to persist the non-zero setting of backend docker-events.timeout server + - type: bind + source: "${DATADIR}/haproxy/haproxy.cfg.template" + target: /usr/local/etc/haproxy/haproxy.cfg.template +############################################################### + whoami: + image: traefik/whoami:latest + container_name: whoami + restart: unless-stopped + security_opt: + - no-new-privileges=true + depends_on: + - traefik + networks: + - traefik-net + environment: + - TZ + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.whoami-rtr.entrypoints=web" + - "traefik.http.routers.whoami-rtr.rule=Host(`whoami.${DOMAINNAME}`)" +############################################################### diff --git a/traefik/stacks/config/traefik.yml b/traefik/stacks/config/traefik.yml new file mode 100644 index 0000000..5bf58d9 --- /dev/null +++ b/traefik/stacks/config/traefik.yml @@ -0,0 +1,256 @@ +################################################################ +# Global configuration - https://doc.traefik.io/traefik/reference/static-configuration/file/ +################################################################ + +global: + checkNewVersion: false + sendAnonymousUsage: false + + +################################################################ +# Entrypoints - https://doc.traefik.io/traefik/routing/entrypoints/ +################################################################ +entryPoints: + web: + address: ":80" + #reusePort: true + # Global HTTP to HTTPS redirection +# http: +# redirections: +# entrypoint: +# to: websecure +# scheme: https + websecure: + address: ":443" + http: + tls: + certResolver: sthomeresolver + #domains: + # - main: "sthome.org" + # sans: + # - "*.sthome.org" + forwardedHeaders: + trustedIPs: + # Cloudflare (https://www.cloudflare.com/ips-v4) + - "173.245.48.0/20" + - "103.21.244.0/22" + - "103.22.200.0/22" + - "103.31.4.0/22" + - "141.101.64.0/18" + - "108.162.192.0/18" + - "190.93.240.0/20" + - "188.114.96.0/20" + - "197.234.240.0/22" + - "198.41.128.0/17" + - "162.158.0.0/15" + - "104.16.0.0/13" + - "104.24.0.0/14" + - "172.64.0.0/13" + - "131.0.72.0/22" + # Local IPs + - "127.0.0.1/32" + - "10.0.0.0/24" + - "192.168.2.0/24" + - "172.16.0.0/12" + + wireguard: + address: ":51820/udp" + + plex: + address: ":32400" + http: + redirections: + entrypoint: + to: websecure + scheme: https + + metrics: + address: ":8082" + + ping: + address: ":8083" + + mariadb: + address: ":8306" + + mysql: + address: ":9306" + + mqtt: + address: ":1883" + + mqttsecure: + address: ":8883" + + mc-bedrock: + address: ":19132/udp" + + mc-java: + address: ":25565/udp" + + mc-java-rcon: + address: ":25575" + + sftp1: + address: ":2022" + sftp2: + address: ":2023" + sftp3: + address: ":2024" + sftp4: + address: ":2025" + sftp5: + address: ":2026" + sftp6: + address: ":2027" + sftp7: + address: ":2028" + sftp8: + address: ":2029" + +ping: + entryPoint: "ping" +################################################################ +# Logs - https://doc.traefik.io/traefik/observability/logs/ +################################################################ +log: + level: DEBUG # Options: DEBUG, PANIC, FATAL, ERROR (Default), WARN, and INFO + filePath: /logs/traefik-container.log # Default is to STDOUT + format: json # Uses text format (common) by default + noColor: false # Recommended to be true when using common + maxSize: 100 # In megabytes + compress: true # gzip compression when rotating + +################################################################ +# Access logs - https://doc.traefik.io/traefik/observability/access-logs/ +################################################################ +accessLog: + addInternals: true # things like ping@internal + filePath: /logs/traefik-access.log # In the Common Log Format (CLF) by default + bufferingSize: 100 # Number of log lines + fields: + names: + StartUTC: drop # Write logs in Container Local Time instead of UTC + filters: + statusCodes: + - "204-299" + - "400-499" + - "500-599" + +################################################################ +# Prometheus - https://doc.traefik.io/traefik/observability/metrics/prometheus/ +################################################################ +metrics: + prometheus: + entryPoint: metrics + buckets: + - 0.1 + - 0.3 + - 1.2 + - 5.0 + addEntryPointsLabels: true + addRoutersLabels: true + addServicesLabels: true + +################################################################ +# API and Dashboard +################################################################ +api: + dashboard: true + # disableDashboardAd: true + # Rely on api@internal and Traefik with Middleware to control access + # insecure: true + +################################################################ +# Providers - https://doc.traefik.io/traefik/providers/docker/ +################################################################ +providers: + docker: + #endpoint: "unix:///var/run/docker.sock" # Comment if using socket-proxy + endpoint: "tcp://traefik_socket-proxy:2375" # Uncomment if using socket proxy + exposedByDefault: false + network: traefik-net # network to use for connections to all containers + # defaultRule: TODO + + # Enable auto loading of newly created rules by watching a directory + file: + # Apps, LoadBalancers, TLS Options, Middlewares, Middleware Chains + directory: /rules # /etc/traefik + watch: true + +################################################################ +# tls +################################################################ +tls: + stores: + default: +# defaultCertificate: +# certFile: /data/sthome-org.pem +# keyFile: /data/sthome-org-key.pem + defaultGeneratedCert: + resolver: solver-dns + domain: + main: sthome.org + sans: + - plex.sthome.org + - emby.sthome.org + - jellyfin.sthome.org + - traefik.sthome.org + +################################################################ +# ACME +################################################################ +certificatesResolvers: +# sthomeresolver: +# acme: +# email: "stuurmcp@telkomsa.net" +# storage: "/data/acme.json" # "/etc/traefik/letsencrypt/acme.json" +# #caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" # Comment out when going prod +# caServer: "https://acme-v02.api.letsencrypt.org/directory" # production: +# dnsChallenge: +# provider: cloudflare +# #delayBeforeCheck: 30 # Default is 2m0s. This changes the delay (in seconds) +# # Custom DNS server resolution +# resolvers: +# - "1.1.1.1:53" +# - "8.8.8.8:53" +## +# sthome-org: +# acme: +# email: "stuurmcp@telkomsa.net" +# storage: "/data/acme.json" # "/etc/traefik/letsencrypt/acme.json" +# #caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" # Comment out when going prod +# caServer: "https://acme-v02.api.letsencrypt.org/directory" # production: +# dnsChallenge: +# provider: cloudflare +# #delayBeforeCheck: 30 # Default is 2m0s. This changes the delay (in seconds) +# # Custom DNS server resolution +# resolvers: +# - "1.1.1.1:53" +# - "8.8.8.8:53" + solver-dns: + acme: + email: "stuurmcp@telkomsa.net" + storage: "/data/acme.json" # "/etc/traefik/letsencrypt/acme.json" + #caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" # Comment out when going prod + caServer: "https://acme-v02.api.letsencrypt.org/directory" # production: + dnsChallenge: + provider: cloudflare + #delayBeforeCheck: 30 # Default is 2m0s. This changes the delay (in seconds) + # Custom DNS server resolution + resolvers: + - "1.1.1.1:53" + - "8.8.8.8:53" + #sthome-net: + # acme: + # email: "stuurmcp@telkomsa.net" + # storage: "/etc/traefik/local/acme.json" # "/data/acme.json" + # caServer: "https://upd.sthome.net/acme-v02.api" # production: + # dnsChallenge: + # provider: sthomelocal + #delayBeforeCheck: 30 # Default is 2m0s. This changes the delay (in seconds) + # Custom DNS server resolution + # resolvers: + # - "10.0.0.15:53" + # - "192.168.2.1:53" + \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-buffering.yml b/traefik/stacks/rules/http-middlewares-buffering.yml new file mode 100644 index 0000000..8e492d9 --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-buffering.yml @@ -0,0 +1,18 @@ +################################################################ +# Middlewares (https://github.com/htpcBeginner/docker-traefik/blob/master/appdata/traefik2/rules/cloudserver/middlewares.yml) +# 2024 update: https://github.com/htpcBeginner/docker-traefik/tree/master/appdata/traefik3/rules/hs +# https://www.smarthomebeginner.com/traefik-docker-compose-guide-2022/ +# +# Dynamic configuration +################################################################ +http: + middlewares: + # Prevent too large of a body + # https://stackoverflow.com/questions/49717670/how-to-config-upload-body-size-restriction-in-traefik + http-mw-buffering: + buffering: + maxRequestBodyBytes: 10485760 + memRequestBodyBytes: 2097152 + maxResponseBodyBytes: 10485760 + memResponseBodyBytes: 2097152 + retryExpression: "IsNetworkError() && Attempts() <= 2" \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-compress-redirect.yml b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-compress-redirect.yml new file mode 100644 index 0000000..a019c9e --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-compress-redirect.yml @@ -0,0 +1,9 @@ +http: + middlewares: + http-mw-rateLimit-secureHeaders-compress-redirect: + chain: + middlewares: + - http-mw-rateLimit + - http-mw-secureHeaders + - http-mw-compress + - http-mw-redirectScheme \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-compress.yml b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-compress.yml new file mode 100644 index 0000000..d29cf8b --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-compress.yml @@ -0,0 +1,8 @@ +http: + middlewares: + http-mw-rateLimit-secureHeaders-compress: + chain: + middlewares: + - http-mw-rateLimit + - http-mw-secureHeaders + - http-mw-compress \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-redirect.yml b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-redirect.yml new file mode 100644 index 0000000..5f4b2a3 --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders-redirect.yml @@ -0,0 +1,8 @@ +http: + middlewares: + http-mw-rateLimit-secureHeaders-redirect: + chain: + middlewares: + - http-mw-rateLimit + - http-mw-secureHeaders + - http-mw-redirectScheme \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders.yml b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders.yml new file mode 100644 index 0000000..e478cfb --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-chain-ratelimit-secureheaders.yml @@ -0,0 +1,7 @@ +http: + middlewares: + http-mw-rateLimit-secureHeaders: + chain: + middlewares: + - http-mw-rateLimit + - http-mw-secureHeaders \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-chain-secureheaders-redirect.yml b/traefik/stacks/rules/http-middlewares-chain-secureheaders-redirect.yml new file mode 100644 index 0000000..dd3dcbb --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-chain-secureheaders-redirect.yml @@ -0,0 +1,7 @@ +http: + middlewares: + http-mw-secureHeaders-redirect: + chain: + middlewares: + - http-mw-secureHeaders + - http-mw-redirectScheme \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-compress.yml b/traefik/stacks/rules/http-middlewares-compress.yml new file mode 100644 index 0000000..9bd8644 --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-compress.yml @@ -0,0 +1,12 @@ +################################################################ +# Middlewares (https://github.com/htpcBeginner/docker-traefik/blob/master/appdata/traefik2/rules/cloudserver/middlewares.yml) +# 2024 update: https://github.com/htpcBeginner/docker-traefik/tree/master/appdata/traefik3/rules/hs +# https://www.smarthomebeginner.com/traefik-docker-compose-guide-2022/ +# +# Dynamic configuration +################################################################ +http: + middlewares: + # Compress to save bandwidth + http-mw-compress: + compress: {} \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-ratelimit.yml b/traefik/stacks/rules/http-middlewares-ratelimit.yml new file mode 100644 index 0000000..94429d9 --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-ratelimit.yml @@ -0,0 +1,14 @@ +################################################################ +# Middlewares (https://github.com/htpcBeginner/docker-traefik/blob/master/appdata/traefik2/rules/cloudserver/middlewares.yml) +# 2024 update: https://github.com/htpcBeginner/docker-traefik/tree/master/appdata/traefik3/rules/hs +# https://www.smarthomebeginner.com/traefik-docker-compose-guide-2022/ +# +# Dynamic configuration +################################################################ +http: + middlewares: + # DDoS Prevention + http-mw-rateLimit: + rateLimit: + average: 100 + burst: 50 \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-redirectscheme.yml b/traefik/stacks/rules/http-middlewares-redirectscheme.yml new file mode 100644 index 0000000..897e753 --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-redirectscheme.yml @@ -0,0 +1,15 @@ +################################################################ +# Middlewares (https://github.com/htpcBeginner/docker-traefik/blob/master/appdata/traefik2/rules/cloudserver/middlewares.yml) +# 2024 update: https://github.com/htpcBeginner/docker-traefik/tree/master/appdata/traefik3/rules/hs +# https://www.smarthomebeginner.com/traefik-docker-compose-guide-2022/ +# +# Dynamic configuration +################################################################ +http: + middlewares: + # Middleware for Redirection + # This can be used instead of global redirection + http-mw-redirectScheme: + redirectscheme: + scheme: https + permanent: true \ No newline at end of file diff --git a/traefik/stacks/rules/http-middlewares-secureheaders.yml b/traefik/stacks/rules/http-middlewares-secureheaders.yml new file mode 100644 index 0000000..5dac440 --- /dev/null +++ b/traefik/stacks/rules/http-middlewares-secureheaders.yml @@ -0,0 +1,36 @@ +################################################################ +# Middlewares (https://github.com/htpcBeginner/docker-traefik/blob/master/appdata/traefik2/rules/cloudserver/middlewares.yml) +# 2024 update: https://github.com/htpcBeginner/docker-traefik/tree/master/appdata/traefik3/rules/hs +# https://www.smarthomebeginner.com/traefik-docker-compose-guide-2022/ +# +# Dynamic configuration +################################################################ +http: + middlewares: + ################################################################ + # Good Basic Security Practices + ################################################################ + http-mw-secureHeaders: + headers: + accessControlAllowMethods: + - GET + - OPTIONS + - PUT + accessControlMaxAge: 100 + hostsProxyHeaders: + - "X-Forwarded-Host" + stsSeconds: 63072000 # 2 years + stsIncludeSubdomains: true + stsPreload: true + forceSTSHeader: true + #customFrameOptionsValue: "allow-from https:{{env "DOMAINNAME"}}" #CSP takes care of this but may be needed for organizr. + customFrameOptionsValue: SAMEORIGIN # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options + contentTypeNosniff: true + browserXssFilter: true + # sslForceHost: true # add sslHost to all of the services + # sslHost: "{{env "DOMAINNAME"}}" + referrerPolicy: "same-origin" + permissionsPolicy: "camera=(), microphone=(), geolocation=(), payment=(), usb=()" + customResponseHeaders: + X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex," + server: "" \ No newline at end of file diff --git a/traefik/stacks/rules/tls-options.yml b/traefik/stacks/rules/tls-options.yml new file mode 100644 index 0000000..d3e2691 --- /dev/null +++ b/traefik/stacks/rules/tls-options.yml @@ -0,0 +1,37 @@ +################################################################ +# TLS Options (https://jellyfin.org/docs/general/networking/traefik2.html#traefik-providertoml) +# toml -> yml +# 2024 updates to cipherSuites from (https://www.smarthomebeginner.com/traefik-v3-docker-compose-guide-2024/) +# +# Set secure options by disabling insecure older TLS/SSL versions +# and insecure ciphers. SNIStrict disabled leaves TLS1.0 open. +# If you have problems with older clients, you can may need to relax +# these minimums. This configuration will give you an A+ SSL security +# score supporting TLS1.2 and TLS1.3 +# +# Dynamic configuration +# https://doc.traefik.io/traefik/https/tls/ +################################################################ +tls: + options: + tls-options: + sniStrict: true + minVersion: VersionTLS12 + cipherSuites: + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 + - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 + - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 + - TLS_CHACHA20_POLY1305_SHA256 + - TLS_FALLBACK_SCSV # Client is doing version fallback. See RFC 7507 + curvePreferences: + # CurveP256, CurveP384, CurveP521, X25519 + # secp256r1, secp384r1, secp521r1, x25519, x448 + - secp521r1 + - secp384r1 + mintls13: + minVersion: VersionTLS13 \ No newline at end of file diff --git a/traefik/stacks/users/common.txt b/traefik/stacks/users/common.txt new file mode 100644 index 0000000..0b6a9a2 --- /dev/null +++ b/traefik/stacks/users/common.txt @@ -0,0 +1,3 @@ +admin:$2y$05$djOyLnsk5p1.wcCLJCXpcehznR3cc04otaSlpED3fSRC9EpRGDkMC +chris:$2y$05$FSl7QIqo.VMe69nm8K.Dv.O05Gi6oad.2qY7oKjgqbPa4eBPintbK +Chris:$2y$05$8r6M8zr0MFIiDLUm1vP1Ee0AP8kMJtDsw4zezFeSDVlWeEOkwuBuC \ No newline at end of file diff --git a/traefik/stacks/users/traefik.txt b/traefik/stacks/users/traefik.txt new file mode 100644 index 0000000..0b6a9a2 --- /dev/null +++ b/traefik/stacks/users/traefik.txt @@ -0,0 +1,3 @@ +admin:$2y$05$djOyLnsk5p1.wcCLJCXpcehznR3cc04otaSlpED3fSRC9EpRGDkMC +chris:$2y$05$FSl7QIqo.VMe69nm8K.Dv.O05Gi6oad.2qY7oKjgqbPa4eBPintbK +Chris:$2y$05$8r6M8zr0MFIiDLUm1vP1Ee0AP8kMJtDsw4zezFeSDVlWeEOkwuBuC \ No newline at end of file diff --git a/traefik/to install htpasswd.txt b/traefik/to install htpasswd.txt new file mode 100644 index 0000000..c81da8e --- /dev/null +++ b/traefik/to install htpasswd.txt @@ -0,0 +1,7 @@ + +Install htpasswd: +apt update & apt install apache2-utils + +Create password hash for user alice with traefik basicauth +echo $(htpasswd -nB alice) | sed -e s/\\$/\\$\\$/g +Enter and confirm password to hash diff --git a/traefik/traefik.cer b/traefik/traefik.cer new file mode 100644 index 0000000..84a77c2 --- /dev/null +++ b/traefik/traefik.cer @@ -0,0 +1,64 @@ +-----BEGIN CERTIFICATE----- +MIIF9TCCBN2gAwIBAgISBNrV+ChCXbPXp2c5HpZP2fuUMA0GCSqGSIb3DQEBCwUA +MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD +EwNSMTAwHhcNMjUwMTMwMDM1MzM3WhcNMjUwNDMwMDM1MzM2WjAdMRswGQYDVQQD +ExJ0cmFlZmlrLnN0aG9tZS5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCdZeExuQpzaJUJmJUnZQMcGLXsAmKZUfT8ieTgcpeV/t/fSBI4thHu9V6H +sB82tc0ZAyrR83Fu/YbbcBYnim5tPC5JkXS5j99dfT5l9zluQLQmLTpSjpY4Vg5W +NhI0JrJOJG/wgLC5abFQuX+QzNfqCe/rkg94Jo6OynpwthsPDw4uMTh0e+2x6BWp +Uq9WekuSk354gai4F/PtqHOFmS2hMRQm+ZJl0VTJrjgUwDANvd6YmLxL8Wpcv1Yl +o9TDGv+hL6ocySY5ctsg+Gf1Xg9jb2XqBS4QDkqH+GRloPI1/2yKd2/b+BzMJEzE +SnLDkAGN0Qzw+zf9vAiJn83NoiQ9VyzpPrgREEmQP1SBA7iQytJh6Og9cdjCMPKH +IHoi0ZpArEDs3REyhA/JhEmH4OlOCrwxm1MJdSJO1gyXkieKJS9HlccPQnpCZlt/ +RQ+sxH11yv5m/A/ybdpRi3lqdWTqFNoVqwsmNUB/Lf9JS6WRaU/V08rB6QzcHjOV +KWk2SpxFLFbczP5Ry4UIWfJEMLy5d5kmBV6hieQ1NSK6tbORSCUHOC9YegOq9k1M +BVXNCX6/iCQLfqgbF0tp+p7/Rmf4RrZDxzN9TuG64hYLqFCDw4lei+PuWMlqEM6V +H5kWP7txt0MeaX+lTzFI3Q3MjTC6ddfytIqYzrr7ByvEw0Sm3wIDAQABo4ICFzCC +AhMwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD +AjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBS164JDxEtFIY52qvRibxklzTGeCjAf +BgNVHSMEGDAWgBS7vMNHpeS8qcbDpHIMEI2iNeHI6DBXBggrBgEFBQcBAQRLMEkw +IgYIKwYBBQUHMAGGFmh0dHA6Ly9yMTAuby5sZW5jci5vcmcwIwYIKwYBBQUHMAKG +F2h0dHA6Ly9yMTAuaS5sZW5jci5vcmcvMB0GA1UdEQQWMBSCEnRyYWVmaWsuc3Ro +b21lLm9yZzATBgNVHSAEDDAKMAgGBmeBDAECATCCAQUGCisGAQQB1nkCBAIEgfYE +gfMA8QB2AMz7D2qFcQll/pWbU87psnwi6YVcDZeNtql+VMD+TA2wAAABlLWNX4sA +AAQDAEcwRQIhAOmeed1rXHwEpxHLT4BkVZoCgX8RQaG4CCML1GxAp/qXAiAtpaP4 +7DF54hCslIBk47y5KmQOeQJM4AQfJPU4TZ0BQAB3AN6FgddQJHxrzcuvVjfF54HG +TORu1hdjn480pybJ4r03AAABlLWNX5kAAAQDAEgwRgIhAJgsdEmkuzw8dVKN4kgY +k+/s9dWdDs/ZgH5+cA2jNWbSAiEA0yT8UAw6UZmnjS9TKP4RGow4IuxN2u92TsYq +KtKEq8kwDQYJKoZIhvcNAQELBQADggEBAFVNBE2AGELcjDuhHNWihxdxcsS2lwv5 +ABLagtpOP4EXaJ352ro/6G4PALoci1QV89SDoMJDLaV0xA67XEezvr4cAHcuesXp +B/+cO2IM70hpVYd+MUx1TSCT6AKCkHu6Pr0w7tWLZ615mXXIcEQLnIPZr+Hlkg0y +oBeuhskkgzl98BKaAbi/vRntQnVe/WiEY2izFL1OXxJ0VQQAmMvSIKzzi6C9MX+n +r6tQlN5LsP/+c5tjzZA5Ya7Byj23Z5pJsPExCpSBA3jjG6t1yX568erMhh2mT947 +BQ3omDw/X579lycDCmIWPHjoYwNg+ug49aU+GhX3ipNeZ5MLJMuc6zQ= +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP +MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy +Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa +Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF +bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL +YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a +/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4 +FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR +mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3 +DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG +MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/ +AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5 +tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG +Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD +VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B +AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo +zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd +u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9 +1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0 +GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh +1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ +QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N +4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz +rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei +RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx +KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/traefik/traefik_jm.txt b/traefik/traefik_jm.txt new file mode 100644 index 0000000..6553ccc --- /dev/null +++ b/traefik/traefik_jm.txt @@ -0,0 +1,61 @@ +https://docs.techdox.nz/traefik/ +https://www.youtube.com/watch?v=wLrmmh1eI94 + +traefik user: 3012 +traefik group: 3011 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*traefik" +# create following datasets if not present +zfs create SSD1/docker/data/traefik +zfs create SSD1/docker/data/traefik/appdata +zfs create SSD1/docker/data/traefik/logs +chown -R traefik:traefik /mnt/SSD1/docker/data/traefik +chmod 600 /mnt/SSD1/docker/data/traefik/appdata + +Create folders +-------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/traefik/secrets +mkdir /mnt/SSD1/docker/stacks/traefik/config +mkdir /mnt/SSD1/docker/stacks/traefik/rules +mkdir /mnt/SSD1/docker/stacks/traefik/users + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in traefik folder, enter: +./cp2nas +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/traefik/ +# This should copy traefik stacks folder to /mnt/SSD1/docker/stacks/traefik + +Creating secrets +---------------- +# In Truenas shell: +cd /mnt/SSD1/docker/stacks/traefik/secrets +echo -n 'your_cf_dns_api_token' > /mnt/SSD1/docker/stacks/traefik/secrets/cf_dns_api_token +chown -R traefik:traefik /mnt/SSD1/docker/stacks/traefik +chmod -R 400 /mnt/SSD1/docker/stacks/traefik + +# Skip the next section if you do not need to use basic-auth middlewares +Creating user password hash strings for user authorisation with basic-auth middlewares +-------------------------------------------------------------------------------------- +# follow steps in "creating user password hash strings for user authorisation with traefik basic-auth middlewares.txt" + +Start traefik +------------- +# In docker shell: +docker compose -f /opt/stacks/traefik/compose.yml up -d + +Certificates +------------ +# The SSL certificates will be stored in /mnt/SSD1/docker/data/traefik/appdata folder in acme.json file +# Keep this folder clean +# If you want to save any certificates in this folder separately, make sure that you manage it, e.g. delete all certificates manually added to this folder when they expire + + + + diff --git a/uptime-kuma/stacks/.env b/uptime-kuma/stacks/.env new file mode 100644 index 0000000..84466ab --- /dev/null +++ b/uptime-kuma/stacks/.env @@ -0,0 +1,19 @@ +################################################################ +APPLICATION_NAME=uptime-kuma + +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +PUID=3058 +PGID=3059 +DOMAINNAME=sthome.org +DNS_RESOLVER=sthomeresolver + +################################################################ + +WEBUI_PORT=3001 \ No newline at end of file diff --git a/uptime-kuma/stacks/.uptime-kuma.env b/uptime-kuma/stacks/.uptime-kuma.env new file mode 100644 index 0000000..38a5465 --- /dev/null +++ b/uptime-kuma/stacks/.uptime-kuma.env @@ -0,0 +1,3 @@ + +PUID=${PUID} +PGID=${PGID} \ No newline at end of file diff --git a/uptime-kuma/stacks/compose.yml b/uptime-kuma/stacks/compose.yml new file mode 100644 index 0000000..a0a629f --- /dev/null +++ b/uptime-kuma/stacks/compose.yml @@ -0,0 +1,44 @@ +networks: + traefik-net: + external: true + +services: + uptime-kuma: + image: louislam/uptime-kuma:1 + hostname: uptime-kuma + restart: always + env_file: .uptime-kuma.env + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/appdata:/app/data" + networks: + - traefik-net + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # http service + # ------------ + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + # + # http middlewares + # ---------------- + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/${APPLICATION_NAME}.txt" + # + # http routers + # ------------ + # http://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # https://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" diff --git a/users.txt b/users.txt new file mode 100644 index 0000000..d5bb186 --- /dev/null +++ b/users.txt @@ -0,0 +1,117 @@ +root:x:0:0:root:/root:/usr/bin/zsh +daemon:x:1:1:Owner of many system processes:/usr/sbin:/usr/sbin/nologin +bin:x:2:2:Binaries Commands and Source:/bin:/usr/sbin/nologin +sys:x:3:3:sys:/dev:/usr/sbin/nologin +sync:x:4:65534:sync:/bin:/bin/sync +games:x:5:60:Games pseudo-user:/usr/games:/usr/sbin/nologin +man:x:6:12:Mister Man Pages:/var/cache/man:/usr/sbin/nologin +lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin +mail:x:8:8:mail:/var/mail:/usr/sbin/nologin +news:x:9:9:News Subsystem:/var/spool/news:/usr/sbin/nologin +uucp:x:10:10:UUCP pseudo-user:/var/spool/uucp:/usr/sbin/nologin +proxy:x:13:13:Packet Filter pseudo-user:/bin:/usr/sbin/nologin +www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin +backup:x:34:34:backup:/var/backups:/usr/sbin/nologin +list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin +irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin +gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin +postgres:x:70:70:postgres:/var/empty:/usr/sbin/nologin +_apt:x:100:65534::/nonexistent:/usr/sbin/nologin +systemd-timesync:x:101:101:systemd Time Synchronization:/run/systemd:/usr/sbin/nologin +systemd-network:x:102:103:systemd Network Management:/run/systemd:/usr/sbin/nologin +systemd-resolve:x:103:104:systemd Resolver:/run/systemd:/usr/sbin/nologin +messagebus:x:104:111:messagebus user:/nonexistent:/usr/sbin/nologin +avahi:x:105:112:avahi user:/nonexistent:/usr/sbin/nologin +_rpc:x:106:65534::/run/rpcbind:/usr/sbin/nologin +statd:x:107:65534::/var/lib/nfs:/usr/sbin/nologin +consul:x:108:113:Consul Daemon:/var/tmp/consul:/usr/sbin/nologin +nvpd:x:109:114:NVIDIA Persistence Daemon:/var/run/nvpd/:/usr/sbin/nologin +nslcd:x:110:115:Nslcd Daemon:/var/tmp/nslcd:/usr/sbin/nologin +sshd:x:111:65534:Secure Shell Daemon:/var/empty:/usr/sbin/nologin +systemd-coredump:x:112:116:systemd Core Dumper:/run/systemd:/usr/sbin/nologin +Debian-snmp:x:113:117::/var/lib/snmp:/bin/false +ntp:x:114:119::/nonexistent:/usr/sbin/nologin +Debian-exim:x:115:120::/var/spool/exim4:/usr/sbin/nologin +tftp:x:116:121:tftp daemon:/srv/tftp:/usr/sbin/nologin +sssd:x:117:122:SSSD system user:/var/lib/sss:/usr/sbin/nologin +tcpdump:x:118:123::/nonexistent:/usr/sbin/nologin +proftpd:x:120:65534::/run/proftpd:/usr/sbin/nologin +ftp:x:121:65534::/nonexistent:/usr/sbin/nologin +nut:x:122:126::/var/lib/nut:/usr/sbin/nologin +dnsmasq:x:123:65534:dnsmasq:/var/lib/misc:/usr/sbin/nologin +ladvd:x:124:127:ladvd user:/var/empty:/usr/sbin/nologin +nova:x:125:129::/var/lib/nova:/bin/bash +haproxy:x:126:130::/var/lib/haproxy:/usr/sbin/nologin +uuidd:x:127:131::/run/uuidd:/usr/sbin/nologin +ntpsec:x:128:135::/nonexistent:/usr/sbin/nologin +tss:x:129:136:TPM software stack:/var/lib/tpm:/bin/false +iperf3:x:130:137::/nonexistent:/usr/sbin/nologin +_chrony:x:131:138:Chrony daemon:/var/lib/chrony:/usr/sbin/nologin +apps:x:568:568:Unprivileged Apps User:/var/empty:/usr/sbin/nologin +webdav:x:666:666:WebDAV Anonymous User:/var/empty:/usr/sbin/nologin +admin:x:950:950:Local Administrator:/home/admin:/usr/bin/zsh +polkitd:x:998:998:polkit:/nonexistent:/usr/sbin/nologin +netdata:x:999:997::/var/lib/netdata:/bin/sh +git:x:1000:1000:git:/mnt/stpool1/Users/git:/usr/bin/bash +chris:x:3000:3000:Chris:/mnt/stpool1/Users/Chris:/usr/bin/zsh +roderique:x:3001:3001:Roderique:/mnt/stpool1/Users/Roderique:/usr/sbin/nologin +zelmique:x:3002:3002:Zelmique:/mnt/stpool1/Users/Zelmique:/usr/sbin/nologin +carlton:x:3003:3003:Carlton:/mnt/stpool1/Users/Carlton:/usr/sbin/nologin +zelna:x:3004:3004:Zelna:/mnt/stpool1/Users/Zelna:/usr/sbin/nologin +lyrique:x:3005:3005:Lyrique:/mnt/stpool1/Users/Lyrique:/usr/sbin/nologin +docker:x:3006:999:docker:/mnt/stpool1/Users/docker:/usr/sbin/nologin +acme:x:3007:3006:acme:/mnt/stpool1/Users/acme:/usr/sbin/nologin +pveuser:x:3008:3007:pveuser:/var/empty:/usr/sbin/nologin +jellyfin:x:3009:3008:jellyfin:/var/empty:/usr/bin/zsh +rename:x:3010:3009:rename:/var/empty:/usr/sbin/nologin +mealie:x:3011:3010:mealie:/var/empty:/usr/sbin/nologin +traefik:x:3012:3011:traefik:/var/empty:/usr/sbin/nologin +vaultwdn:x:3013:3012:vaultwarden:/var/empty:/usr/sbin/nologin +authentik:x:3014:3013:authentik:/var/empty:/usr/sbin/nologin +plex:x:3015:3017:plex:/var/empty:/usr/sbin/nologin +gitea:x:3016:3015:gitea:/var/empty:/usr/sbin/nologin +emby:x:3017:3016:emby:/var/empty:/usr/sbin/nologin +photovw:x:3018:3056:photovw:/var/empty:/usr/sbin/nologin +wg-easy:x:3019:3018:wg-easy:/var/empty:/usr/sbin/nologin +wguard:x:3020:3019:wguard:/var/empty:/usr/sbin/nologin +prometh:x:3021:3020:prometheus:/var/empty:/usr/sbin/nologin +grafana:x:3022:3021:grafana:/var/empty:/usr/sbin/nologin +sonarr:x:3023:3017:sonarr:/var/empty:/usr/sbin/nologin +prowlarr:x:3024:3023:prowlarr:/var/empty:/usr/sbin/nologin +radarr:x:3025:3024:radarr:/var/empty:/usr/sbin/nologin +lidarr:x:3026:3025:lidarr:/var/empty:/usr/sbin/nologin +readarr:x:3027:3026:readarr:/var/empty:/usr/sbin/nologin +qbittorr:x:3028:3027:qbittorrent:/var/empty:/usr/sbin/nologin +gluetun:x:3029:3028:gluetun:/var/empty:/usr/sbin/nologin +audbkshelf:x:3030:3029:audiobookshelf:/var/empty:/usr/sbin/nologin +overseer:x:3031:3030:overseerr:/var/empty:/usr/sbin/nologin +calibre:x:3032:3031:calibre:/var/empty:/usr/sbin/nologin +cfddns:x:3033:3032:cloudflareddns:/var/empty:/usr/sbin/nologin +collabor:x:3034:3033:collabora:/var/empty:/usr/sbin/nologin +firefly3:x:3035:3034:fireflyiii:/var/empty:/usr/sbin/nologin +firefox:x:3036:3035:firefox:/var/empty:/usr/sbin/nologin +handbrk:x:3037:3036:handbrake:/var/empty:/usr/sbin/nologin +hmeassist:x:3038:3037:home-assistant:/var/empty:/usr/sbin/nologin +jdownldr2:x:3039:3038:jdownloader2:/var/empty:/usr/sbin/nologin +kavita:x:3040:3039:kavita:/var/empty:/usr/sbin/nologin +librespd:x:3041:3040:librespeed:/var/empty:/usr/sbin/nologin +mediaelc:x:3042:3041:mediaelch:/var/empty:/usr/sbin/nologin +minecraft:x:3043:3042:minecraft:/var/empty:/usr/sbin/nologin +digikam:x:3044:3043:digikam:/var/empty:/usr/sbin/nologin +minio:x:3045:3044:minio:/var/empty:/usr/sbin/nologin +mkvtlnix:x:3046:3045:mkvtoolnix:/var/empty:/usr/sbin/nologin +mosquitt:x:3047:3046:mosquitto:/var/empty:/usr/sbin/nologin +nxtcloud:x:3048:3047:nextcloud:/var/empty:/usr/sbin/nologin +onlyoff:x:3049:3048:onlyoffice-document-server:/var/empty:/usr/sbin/nologin +rootapp:x:3050:3049:rootapp:/var/empty:/usr/sbin/nologin +sheetabl:x:3051:3050:sheetable:/var/empty:/usr/sbin/nologin +songkong:x:3052:3051:songkong:/var/empty:/usr/sbin/nologin +swebsvr:x:3053:3052:static-web-server:/var/empty:/usr/sbin/nologin +syncthin:x:3054:3053:syncthing:/var/empty:/usr/sbin/nologin +tautulli:x:3055:3054:tautulli:/var/empty:/usr/sbin/nologin +pihole:x:3056:3057:pihole:/var/empty:/usr/sbin/nologin +dashy:x:3057:3058:dashy:/var/empty:/usr/sbin/nologin +uptime-k:x:3058:3059:uptime-kuma:/var/empty:/usr/sbin/nologin +pgadmin:x:5050:5050:pgadmin:/mnt/stpool1/Users/pgadmin:/usr/bin/zsh +libvirt-qemu:x:64055:106:Libvirt Qemu:/var/lib/libvirt:/usr/sbin/nologin +nobody:x:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin diff --git a/vaultwarden/stacks/.env b/vaultwarden/stacks/.env new file mode 100644 index 0000000..5c52064 --- /dev/null +++ b/vaultwarden/stacks/.env @@ -0,0 +1,39 @@ +################################################################ +APPLICATION_NAME=vaultwarden + +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +PUID=3013 +PGID=3012 +TZ=Africa/Johannesburg +DOMAINNAME=sthome.org +WEBUI_PORT=80 +DNS_RESOLVER=sthomeresolver + +################################################################ + +#ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$/E2XDKhJuDLlUCO011cel6qqH5w0J9iA45pbgY7bpOM$$Ua9OC9+mEEUtZP7o+yU/aLq0WKqz1vfFU1lrDh6VC5Q +#ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$TDdUbzgwZEtrek5YV1hRK1VIREEvbklPNHE4cHloa2wwU3MwRDd3RVNNdz0$$/Z1bmtI4TX45P+JZF3il9dLMKz0ju9hRUwftdRvf9vA +#ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$U3QwellkcjFHUGkrK0lpbGZrM2wyNHlUb25xdU4vSlR4ME1yK09Wb2ZOYz0$$93CJiTWKnaPOP60CXm1guFFh5hlRObfjk5P3ZuXl+xU +ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$DKzckzPLq9/KxC+MfjPKVY16hZFbXfj3V4g7Viu5A80$$pk2l06ibGTsJOhaI7DKvcycvjrFmretqWGCjnNjcLtg +################################################################ + +DB_TYPE=postgres +POSTGRES_DB_PORT=5432 + +# postgresql +POSTGRES_DB_FILE=/run/secrets/vaultwarden_postgresql_database +POSTGRES_USER_FILE=/run/secrets/vaultwarden_postgresql_username +POSTGRES_PASSWORD_FILE=/run/secrets/vaultwarden_postgresql_password + +# vaultwarden doesn't parse ${env_var} within another env_var, so had to expand url and create composite secret +DATABASE_URL_FILE=/run/secrets/vaultwarden_database_url + + + diff --git a/vaultwarden/stacks/.postgresql.env b/vaultwarden/stacks/.postgresql.env new file mode 100644 index 0000000..0d95871 --- /dev/null +++ b/vaultwarden/stacks/.postgresql.env @@ -0,0 +1,11 @@ + +PUID=70 +PGID=70 +TZ=${TZ} + +POSTGRES_DB_PORT=${POSTGRES_DB_PORT} +POSTGRES_DB_FILE=${POSTGRES_DB_FILE} +POSTGRES_USER_FILE=${POSTGRES_USER_FILE} +POSTGRES_PASSWORD_FILE=${POSTGRES_PASSWORD_FILE} + + diff --git a/vaultwarden/stacks/.vaultwarden.env b/vaultwarden/stacks/.vaultwarden.env new file mode 100644 index 0000000..badc784 --- /dev/null +++ b/vaultwarden/stacks/.vaultwarden.env @@ -0,0 +1,27 @@ +################################################################ + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +SIGNUPS_ALLOWED=false # Set to true for initialising, i.e. for first user signup. After first signup, set to false, then restart vaultwarden stack + +WEBSOCKET_ENABLED=false + +#ROCKET_TLS={certs="/ssl/certs/certs.pem",key="/ssl/private/key.pem"} # specific to the Rocket web server + +ADMIN_TOKEN=${ADMIN_TOKEN} + +DOMAIN=https://${APPLICATION_NAME}.${DOMAINNAME} + +# mailer +SMTP_PORT=25 +SMTP_SECURITY=starttls +SMTP_HOST_FILE=/run/secrets/smtp_host +SMTP_FROM_FILE=/run/secrets/smtp_from +SMTP_USERNAME_FILE=/run/secrets/smtp_username +SMTP_PASSWORD_FILE=/run/secrets/smtp_password + +# database +DB_TYPE=${DB_TYPE} +DATABASE_URL_FILE=${DATABASE_URL_FILE} diff --git a/vaultwarden/stacks/compose.yml b/vaultwarden/stacks/compose.yml new file mode 100644 index 0000000..d22fe35 --- /dev/null +++ b/vaultwarden/stacks/compose.yml @@ -0,0 +1,84 @@ +name: vaultwarden + +secrets: + vaultwarden_postgresql_database: + file: "${SECRETSDIR}/vaultwarden_postgresql_database" + vaultwarden_postgresql_username: + file: "${SECRETSDIR}/vaultwarden_postgresql_username" + vaultwarden_postgresql_password: + file: "${SECRETSDIR}/vaultwarden_postgresql_password" + vaultwarden_database_url: + file: "${SECRETSDIR}/vaultwarden_database_url" + smtp_from: + file: "${SECRETSDIR}/smtp_from" + smtp_username: + file: "${SECRETSDIR}/smtp_username" + smtp_password: + file: "${SECRETSDIR}/smtp_password" + smtp_host: + file: "${SECRETSDIR}/smtp_host" + +networks: + traefik-net: + external: true + vaultwarden-net: + external: true + +services: + vaultwarden: + image: vaultwarden/server:latest + hostname: "${APPLICATION_NAME}" + networks: + - traefik-net + - vaultwarden-net + env_file: .vaultwarden.env + secrets: + - vaultwarden_database_url + - smtp_from + - smtp_username + - smtp_password + - smtp_host + volumes: + - "${DATADIR}/appdata:/data:rw" + restart: unless-stopped + depends_on: + postgresql: + condition: service_healthy + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${WEBUI_PORT}" + + postgresql: + image: postgres:16-alpine + hostname: "vaultwarden_postgresql" + env_file: .postgresql.env + shm_size: 128mb # https://hub.docker.com/_/postgres + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + networks: + vaultwarden-net: + aliases: ["vaultwarden_postgresql"] + secrets: + - ${APPLICATION_NAME}_postgresql_database + - ${APPLICATION_NAME}_postgresql_username + - ${APPLICATION_NAME}_postgresql_password + volumes: + - "${DATADIR}/pgdata:/var/lib/postgresql/data" + - "${DATADIR}/pgbackups:/mnt/backups" \ No newline at end of file diff --git a/vaultwarden/vaultwarden_jm.txt b/vaultwarden/vaultwarden_jm.txt new file mode 100644 index 0000000..6b7ec20 --- /dev/null +++ b/vaultwarden/vaultwarden_jm.txt @@ -0,0 +1,105 @@ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: vaultwdn +Username: vaultwdn +Disable Password: +Email: +Create New Primary Group: +Create Home Directory: +Samba Authentication: +Save + +PUID: 3013 +PGID: 3012 +Update .env file accordingly (PUID, PGID) + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*vaultwarden" +# create following datasets if not present +zfs create SSD1/docker/data/vaultwarden +zfs create SSD1/docker/data/vaultwarden/appdata +zfs create SSD1/docker/data/vaultwarden/config +zfs create SSD1/docker/data/vaultwarden/pgdata +zfs create SSD1/docker/data/vaultwarden/pgbackups +chown -R vaultwdn:vaultwdn /mnt/SSD1/docker/data/vaultwarden +chown -R postgres:postgres /mnt/SSD1/docker/data/vaultwarden/pgdata +chown -R postgres:postgres /mnt/SSD1/docker/data/vaultwarden/pgbackups +chmod 700 /mnt/SSD1/docker/data/vaultwarden/pgdata +chmod 700 /mnt/SSD1/docker/data/vaultwarden/pgbackups + +Create folder +------------- +# In Truenas shell: +mkdir -p /mnt/SSD1/docker/stacks/vaultwarden/secrets +mkdir /mnt/SSD1/docker/stacks/vaultwarden/scripts +chown -R vaultwdn:vaultwdn /mnt/SSD1/docker/stacks/vaultwarden/scripts/ + +Create secrets +-------------- +In Truenas shell: +cd /mnt/SSD1/docker/stacks/vaultwarden/secrets/ +# database secrets +echo -n 'vaultwarden' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/vaultwarden_postgresql_database +echo -n 'vaultwarden' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/vaultwarden_postgresql_username +openssl rand 64 | base64 -w 0 | sed 's/[\$,\#,/,+,=]//g' | cut -c -64 | tr -d '\n' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/vaultwarden_postgresql_password +# for vaultwarden's benefit +cd /mnt/SSD1/docker/stacks/vaultwarden/secrets/ +echo -n "postgres://$(cat vaultwarden_postgresql_username):$(cat vaultwarden_postgresql_password)@vaultwarden_postgresql:5432/$(cat vaultwarden_postgresql_database)" > vaultwarden_database_url +# smtp email secrets +echo -n 'your_smtp_destination' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/smtp_destination +echo -n 'your_smtp_from' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/smtp_from +echo -n 'your_smtp_host' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/smtp_host +echo -n 'your_smtp_username' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/smtp_username +echo -n 'your_smtp_password' > /mnt/SSD1/docker/stacks/vaultwarden/secrets/smtp_password +# restrict access +chown -R vaultwdn:vaultwdn /mnt/SSD1/docker/stacks/vaultwarden/secrets/ +chmod -R 400 /mnt/SSD1/docker/stacks/vaultwarden/secrets/ +# read existing acl permissions, if any +getfacl /mnt/SSD1/docker/stacks/vaultwarden/secrets +# set acl permissions +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/vaultwarden/secrets +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/vaultwarden/secrets/vaultwarden_postgresql_password +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/vaultwarden/secrets/vaultwarden_postgresql_username +setfacl -m u:postgres:4 /mnt/SSD1/docker/stacks/vaultwarden/secrets/vaultwarden_postgresql_database +# NB! if you want to remove all acl entries from a folder recursively, use setfacl -b -R +# to list secrets in secrets dir +cd /mnt/SSD1/docker/stacks/vaultwarden/secrets +for i in $(ls -1); do echo $i = `cat $i`; done | sort + +Copy folder to docker stacks +---------------------------- +In Windows cmd shell in vaultwarden parent (apps) folder, enter: +./cp2nas 10.0.0.20 vaultwarden +# or +pscp -P 22 -r vaultwarden/stacks/*.* root@10.0.0.20:/mnt/SSD1/docker/stacks/vaultwarden/ + +Generating admin token +---------------------- +# Start vaultwarden using Dockge +# In docker shell, enter: +docker exec -it vaultwarden-vaultwarden-1 /vaultwarden hash +# Enter strong but memorable password +# Add the string starting with ADMIN_TOKEN to the .vaultwarden.env file +# Edit the string replacing all $ with $$ and removing single quotes around the string value. After the edit, there should be 5 x $$ in the string and no single quotes. +# For example (before and after edit): +# before: ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$Dc3fvaWmkxiZ3PPeVxLNZkTwKghY31S+2bHjN0qZ8PQ$C7p/sWCzfa137Q2coqphcz3WSp2aw4v4TZ/JT9ascTY' +# after : ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$Dc3fvaWmkxiZ3PPeVxLNZkTwKghY31S+2bHjN0qZ8PQ$$C7p/sWCzfa137Q2coqphcz3WSp2aw4v4TZ/JT9ascTY +# Restart vaultwarden stack +# You can login as admin using https://vaultwarden.sthome.org/admin and entering the password used to generate the ADMIN_TOKEN + +Changing URL on Opera browser Bitwarden extension +------------------------------------------------- +Left click on Bitwarden icon (left bottom corner) +Click on Log out +Underneath email address, left click down arrow next to self-hosted +Click on self-hosted +Change the Server URL +Click on Save +Click on Continue +Enter master password of new vaultwarden URL +Click Log in with master password diff --git a/wg-easy/21733_rev1.json b/wg-easy/21733_rev1.json new file mode 100644 index 0000000..6590d61 --- /dev/null +++ b/wg-easy/21733_rev1.json @@ -0,0 +1,860 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "11.1.3" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Dashboard for wg-easy exporter\r\nhttps://github.com/wg-easy/wg-easy", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "wireguard_configured_peers{job=\"$job\", instance=\"$node\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Configured Peers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "wireguard_enabled_peers{job=\"$job\", instance=\"$node\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Enabled Peers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "wireguard_connected_peers{job=\"$job\", instance=\"$node\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Connected Peers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "decimals": 0, + "fieldMinMax": false, + "mappings": [], + "min": 1, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Last *" + }, + "properties": [ + { + "id": "displayName", + "value": "Online" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Field" + }, + "properties": [ + { + "id": "displayName", + "value": "Client" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 7, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "exemplar": false, + "expr": "wireguard_latest_handshake_seconds{job=\"$job\", instance=\"$node\"}", + "format": "time_series", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{name}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Online Clients", + "transformations": [ + { + "id": "reduce", + "options": { + "reducers": [ + "lastNotNull" + ] + } + }, + { + "id": "filterByValue", + "options": { + "filters": [ + { + "config": { + "id": "equal", + "options": { + "value": "" + } + }, + "fieldName": "Last *" + } + ], + "match": "any", + "type": "exclude" + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value #RX" + }, + "properties": [ + { + "id": "displayName", + "value": "Upload" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #TX" + }, + "properties": [ + { + "id": "displayName", + "value": "Download" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "name" + }, + "properties": [ + { + "id": "displayName", + "value": "Client" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 12, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Tx" + } + ] + }, + "pluginVersion": "11.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "exemplar": false, + "expr": "sum by(name) (wireguard_received_bytes{job=\"$job\", instance=\"$node\"})", + "format": "table", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": true, + "legendFormat": "{{name}}", + "range": false, + "refId": "RX", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "exemplar": false, + "expr": "sum by(name) (wireguard_sent_bytes{job=\"$job\", instance=\"$node\"})", + "format": "table", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": true, + "interval": "", + "legendFormat": "{{name}}", + "range": false, + "refId": "TX", + "useBackend": false + } + ], + "title": "Panel Title", + "transformations": [ + { + "id": "merge", + "options": {} + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "sent 10.70.0.2" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byValue", + "options": { + "op": "gte", + "reducer": "allIsZero", + "value": 0 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": false + } + } + ] + }, + { + "matcher": { + "id": "byValue", + "options": { + "op": "gte", + "reducer": "allIsNull", + "value": 0 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": false + } + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 15 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "min" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "irate(wireguard_received_bytes{job=\"$job\", instance=\"$node\"}[5m])", + "format": "time_series", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "intervalFactor": 1, + "legendFormat": "received {{name}}", + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "irate(wireguard_sent_bytes{job=\"$job\", instance=\"$node\"}[5m])", + "format": "time_series", + "fullMetaSearch": false, + "includeNullMetadata": true, + "intervalFactor": 1, + "legendFormat": "sent {{name}}", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Throughput", + "type": "timeseries" + } + ], + "refresh": "10s", + "schemaVersion": 39, + "tags": [ + "prometheus", + "network", + "Wireguard", + "wg-easy" + ], + "templating": { + "list": [ + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(wireguard_configured_peers,job)", + "hide": 0, + "includeAll": false, + "label": "Job", + "multi": false, + "name": "job", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(wireguard_configured_peers,job)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(wireguard_configured_peers{job=\"$job\"},instance)", + "hide": 0, + "includeAll": false, + "label": "Node", + "multi": false, + "name": "node", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(wireguard_configured_peers{job=\"$job\"},instance)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "Europe/Moscow", + "title": "WireGuard wg-easy", + "uid": "c0T_8RkZz", + "version": 15, + "weekStart": "monday", + "gnetId": 21733 +} \ No newline at end of file diff --git a/wg-easy/cp2nas.ps1 b/wg-easy/cp2nas.ps1 new file mode 100644 index 0000000..6778989 --- /dev/null +++ b/wg-easy/cp2nas.ps1 @@ -0,0 +1,57 @@ +############### MAIN ############### +$Main = +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + [Parameter(Mandatory=$false)] + [string[]] $apps + ) + If($PSBoundParameters.ContainsKey("apps")) { + foreach ($appname in $apps) + { + copyfolder $destHost "$appname\stacks" $appname + } + } + else { + $appname="$pwd".Split("\\")[-1] + copyfolder $destHost "stacks" $appname + } +} + +################################### +Function copyfolder +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $destHost, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $srcdir, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string] $appname + ) + if (-Not(Test-Path -Path $srcdir)) { + Write-Host "Source path doesn't exist: ""$PSScriptRoot\$srcdir\*.*"". No files copied!" -ForegroundColor Red + Write-Host "Usage: in app folder : ./cp2nas DEST|IP" + Write-Host " in app parent folder: ./cp2nas DEST|IP app1, app2, app3, ..." + return + } + $destStacks="/mnt/SSD1/docker/stacks/" + $destDir=$destStacks+$appname+"/" + Write-Host "pscp -P 22 -r ""$srcdir\*.*"" root@${destHost}:""${destDir}""" -ForegroundColor Green + Write-Host "Copying to ${destHost}:""${destStacks}" -NoNewline + Write-Host "${appname}/" -ForegroundColor DarkYellow -NoNewline + Write-Host """:" + pscp -P 22 -r "$srcdir\*.*" root@${destHost}:""${destDir}"" +} + +################################### +& $Main @Args \ No newline at end of file diff --git a/wg-easy/stacks/.env b/wg-easy/stacks/.env new file mode 100644 index 0000000..8bb05f5 --- /dev/null +++ b/wg-easy/stacks/.env @@ -0,0 +1,40 @@ +################################################################ +APPLICATION_NAME=wg-easy + +DOCKERDIR=/mnt/SSD1/docker/ + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets + +PUID=3019 +PGID=3018 +DOMAINNAME=sthome.org +TZ=Africa/Johannesburg + +PORT=51821 +WG_PORT=51820 +WG_CONFIG_PORT=92820 +################################################################ +#PEERS=10 + +# Change this to your host's public address +WG_HOST=vpn.sthome.org + +# Optional: +# generate PASSWORD_HASH with: +# docker run --rm -it ghcr.io/wg-easy/wg-easy wgpw 'YOUR_PASSWORD' | sed -e s/\\$/\\$\\$/g # NB: the single quotes around YOUR_PASSWORD +PASSWORD_HASH=$$2a$$12$$S9vnQ5EtnaXhsjpMLUNR0eervb/Koooa26VrzAjjIGbWRpxuHUenS # NB: the single quotes around the hash should be removed, hint = a + +WG_DEFAULT_ADDRESS=10.8.0.x +WG_DEFAULT_DNS=192.168.2.1, 10.0.0.1, 1.1.1.1 +WG_ALLOWED_IPS=0.0.0.0/0, ::/0 +WG_PERSISTENT_KEEPALIVE=25 + +# generate PROMETHEUS_METRICS_PASSWORD with: +# docker run --rm -it ghcr.io/wg-easy/wg-easy wgpw 'YOUR_PASSWORD' | sed -e s/\\$/\\$\\$/g # NB: the single quotes around YOUR_PASSWORD +# PROMETHEUS_METRICS_PASSWORD=$$2a$$12$$h37gtaEp5GIHk7OooBb13O4LAiIefvcDIVUtMR62E1jgwMfGMM2oC # NB: the single quotes around the hash should be removed + + + diff --git a/wg-easy/stacks/.wg-easy.env b/wg-easy/stacks/.wg-easy.env new file mode 100644 index 0000000..5e94775 --- /dev/null +++ b/wg-easy/stacks/.wg-easy.env @@ -0,0 +1,41 @@ +################################################################ + +PUID=${PUID} +PGID=${PGID} +TZ=${TZ} + +################################################################ +#PEERS=10 +LANG=en +WG_HOST=${WG_HOST} + +# Optional: +WG_MTU=1400 +WG_PERSISTENT_KEEPALIVE=25 +# +# WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt +# WG_POST_UP=echo "Post Up" > /etc/wireguard/post-up.txt +# WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt +# WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt +# +# UI_TRAFFIC_STATS=true +# UI_CHART_TYPE=0 # (0 Charts disabled, 1 # Line chart, 2 # Area chart, 3 # Bar chart) +# WG_ENABLE_ONE_TIME_LINKS=true +UI_ENABLE_SORT_CLIENTS=true +# WG_ENABLE_EXPIRES_TIME=true +# + +ENABLE_PROMETHEUS_METRICS=false # No point in enabling metrics, as currently (2024/12) this is not supported by the production version of wg-easy + +PORT=${PORT} +WG_PORT=${WG_PORT} +# WG_CONFIG_PORT=${WG_CONFIG_PORT} +# PROMETHEUS_METRICS_PASSWORD=${PROMETHEUS_METRICS_PASSWORD} +PASSWORD_HASH=${PASSWORD_HASH} +WG_DEFAULT_ADDRESS=${WG_DEFAULT_ADDRESS} +WG_DEFAULT_DNS=${WG_DEFAULT_DNS} +WG_ALLOWED_IPS=${WG_ALLOWED_IPS} + + + + diff --git a/wg-easy/stacks/compose.yml b/wg-easy/stacks/compose.yml new file mode 100644 index 0000000..621eaaa --- /dev/null +++ b/wg-easy/stacks/compose.yml @@ -0,0 +1,60 @@ +name: wg-easy + +networks: + traefik-net: + external: true + +services: + wg-easy: + image: ghcr.io/wg-easy/wg-easy:latest + hostname: wg-easy + restart: unless-stopped + env_file: .wg-easy.env + networks: + - traefik-net + cap_add: + - NET_ADMIN + sysctls: + - net.ipv4.ip_forward=1 + - net.ipv4.conf.all.src_valid_mark=1 + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + - "${DATADIR}/wireguard:/etc/wireguard" + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + # + # udp service + # ------------ + - "traefik.udp.services.wireguard-svc.loadbalancer.server.port=${WG_PORT}" + # + # udp router + # ---------- + - "traefik.udp.routers.wireguard-rtr.entrypoints=wireguard" + # assign service to router + - "traefik.udp.routers.wireguard-rtr.service=wireguard-svc" + # + # http service + # ------------ + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${PORT}" + # + # http routers + # ------------ + # http://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`) || Host(`${WG_HOST}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + # assign service to router + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + # https://appname.domainname/ + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${APPLICATION_NAME}.${DOMAINNAME}`)&& PathPrefix(`/`) || Host(`${WG_HOST}`)&& PathPrefix(`/`)" + # attach middlewares to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + #- "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" # uncomment and test to see if VPN works correctly BEFORE making permanent + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + # assign service to router + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" diff --git a/wg-easy/wg-easy_jm.txt b/wg-easy/wg-easy_jm.txt new file mode 100644 index 0000000..c572065 --- /dev/null +++ b/wg-easy/wg-easy_jm.txt @@ -0,0 +1,61 @@ +https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: wg-easy +Username: wg-easy +Disable Password: +Email: stuurmcp@telkomsa.net +UID: 3019 +Create New Primary Group: +Create Home Directory: +Samba Authentication: +Save +Credentials -> Local Groups -> Add +Name: wg-easy +GID: 3018 + +wg-easy UID: 3019 +wg-easy GID: 3018 + +Create datasets +--------------- +/mnt/SSD1/docker/data/wg-easy ; set Owner:Group to wg-easy:wg-easy +/mnt/SSD1/docker/data/wg-easy/wireguard ; set Owner:Group to wg-easy:wg-easy + +Create secrets +-------------- +# In docker shell: +cd /opt/stacks/wg-easy/secrets +# generate password hash and convert $ in hash to $$; password must be surrounded by single quotes +docker run --rm -it ghcr.io/wg-easy/wg-easy wgpw 'YOUR_PASSWORD' | sed -e s/\\$/\\$\\$/g +# Remove the single quotes from the generated hash and copy the result to local stacks\.env file +# Repeat the above for the prometheus metrics password + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in wg-easy folder, enter: +./cp2nas 10.0.0.20 +# OR +pscp -P 22 -r stacks/*.* root@10.0.0.20:/mnt/SSD1/docker/stacks/wg-easy/ +# The above should copy compose.yaml and .env to /mnt/SSD1/docker/stacks/wg-easy + +Add traefik UDP entrypoint +-------------------------- +Assuming that WG_PORT=51820 in .env file: +If not present, add the following under "entrypoints:" in /opt/stacks/config/traefik.yml + wireguard: + address: ":51820/udp" + +If not present, add the following under "ports:" in /opt/stacks/compose.yml + - target: 51820 + published: 51820 + protocol: udp + mode: host +Execute the above by editing traefik\stacks\compose.yml and traefik\stacks\config\traefik.yml on local computer and then copying to nas/server + + + + + diff --git a/www-sthome/data/appdata/www/.gitignore b/www-sthome/data/appdata/www/.gitignore new file mode 100644 index 0000000..1408ff6 --- /dev/null +++ b/www-sthome/data/appdata/www/.gitignore @@ -0,0 +1,6 @@ +# https://git-scm.com/docs/gitignore +# https://help.github.com/articles/ignoring-files +# Example.gitignore files : https://github.com/github/gitignore +_notes/ +/bower_components/ +/node_modules/ \ No newline at end of file diff --git a/www-sthome/data/appdata/www/index.html b/www-sthome/data/appdata/www/index.html new file mode 100644 index 0000000..6ae8cb5 --- /dev/null +++ b/www-sthome/data/appdata/www/index.html @@ -0,0 +1,18 @@ + + + + + + STHOME Upload Server + +

Welcome to sthome site

+ +
+
+ Select file to upload: + + +
+
+ + \ No newline at end of file diff --git a/www-sthome/data/appdata/www/style.css b/www-sthome/data/appdata/www/style.css new file mode 100644 index 0000000..bb150b4 --- /dev/null +++ b/www-sthome/data/appdata/www/style.css @@ -0,0 +1,113 @@ +@charset "utf-8"; +/* CSS Document */ + +body { + font-family: Roboto; + background-color: #CCCCFF; + padding: 0px; + margin: 0px; +} +body img { + border : 0px; + text-decoration: none; + } +#container { + background-color: #FFFFFF; + width: 80%; + margin: 10px auto 10px auto; + padding: 10px; +} +#masthead { + background-color: #CC99FF; + background: url('images/top-bnr-8.jpg') center; + height: 170px; +} +#top-nav { + border-top: thin solid #1D01D3; + border-bottom: thin solid #1D01D3; + background-color: #FFFFFF; + padding-top: 10px; + padding-bottom: 10px; +} +#left-nav { + padding: 5px; + width: 180px; + float: left; + margin: 20px 0px 10px 0px; + border: thin dashed #EF769A; + font-size: .9em; +} +#main-content { + background-color: #e1e1F8; + margin: 20px 10px 10px 200px; +} +#footer { + clear: both; + text-align: center; + padding-top: 10px; + padding-bottom: 10px; +} +#footer p { margin-top: 0px; margin-bottom: 0px;} +#top-nav ul { + text-align: center; + list-style-type: none; + margin: 0px; + padding: 0px; +} +#top-nav ul li { + display: inline; +} +#top-nav ul li a { + color: #FFFFFF; + background-color: #1D01D3; + border-color: #FFFFFF; + padding: .2em .75em .2em .75em; + border-right-width: 1px; + border-left-width: 1px; + border-right-style: solid; + border-left-style: solid; +} +#top-nav ul li a:hover { + color: #000000; + background-color: #FFFFCC; + border: 1px solid #99BF99; +} +#left-nav ul { + list-style-type: none; + padding: 0px; + margin: 0px; +} +#left-nav ul li { + padding-top: 0px; + padding-bottom: 0px; + color: #FFFFFF; +} +#left-nav ul li a { + color: #FFFFFF; + text-decoration: none; + background-color: #3717FD; + padding: 5px 0px 5px 8px; + display: block; +} +#left-nav ul li a:visited { + color: #FFFFbb; +} +#left-nav ul li a:hover { + color: #000000; + background-color: #FFFFCC; +} +#left-nav .headerbar { + color: #FFFFFF; + font-size: 1.1em; + text-transform: uppercase; + display: block; + background-color: #3717FD; + padding: 4px 2px 4px 2px; +} +.heading1 { + color: #00008B; +} +.heading2 { + color: #00008B; +} + diff --git a/www-sthome/data/appdata/www/upload.php b/www-sthome/data/appdata/www/upload.php new file mode 100644 index 0000000..5fa41a1 --- /dev/null +++ b/www-sthome/data/appdata/www/upload.php @@ -0,0 +1,51 @@ + 500000) { // 500kb + echo "Sorry, your file is too large."; + $uploadOk = 0; + } + + // Allow certain file formats + if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" + && $imageFileType != "gif" ) { + echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed."; + $uploadOk = 0; + } + + // Check if $uploadOk is set to 0 by an error + if ($uploadOk == 0) { + echo "Sorry, your file was not uploaded."; + // if everything is ok, try to upload file + } else { + if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) { + echo "The file ". htmlspecialchars(basename( $_FILES["fileToUpload"]["name"])). " has been uploaded."; + } else { + echo "Sorry, there was an error uploading your file."; + } + } + } + ?> \ No newline at end of file diff --git a/www-sthome/data/config/nginx.conf b/www-sthome/data/config/nginx.conf new file mode 100644 index 0000000..4c85b8f --- /dev/null +++ b/www-sthome/data/config/nginx.conf @@ -0,0 +1,33 @@ + +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + 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; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} diff --git a/www-sthome/data/config/sites-enabled/sthome.conf b/www-sthome/data/config/sites-enabled/sthome.conf new file mode 100644 index 0000000..5450eaa --- /dev/null +++ b/www-sthome/data/config/sites-enabled/sthome.conf @@ -0,0 +1,11 @@ + +server { + listen 80; + listen [::]:80; + server_name www.sthome.org; + root /var/sites/www/; + index index.html index/htm; + location / { + try_files $uri $uri/ =404 ; + } +} \ No newline at end of file diff --git a/www-sthome/data/config/templates/default.conf.template b/www-sthome/data/config/templates/default.conf.template new file mode 100644 index 0000000..2820d5e --- /dev/null +++ b/www-sthome/data/config/templates/default.conf.template @@ -0,0 +1,45 @@ +server { +# listen ${NGINX_PORT}; +# listen [::]:${NGINX_PORT}; +# server_name ${NGINX_HOST}; + + access_log /var/log/nginx/host.access.log main; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + location ~ \.php$ { + root html; + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + include fastcgi_params; + } + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} + +} \ No newline at end of file diff --git a/www-sthome/stacks/.env b/www-sthome/stacks/.env new file mode 100644 index 0000000..1d6010a --- /dev/null +++ b/www-sthome/stacks/.env @@ -0,0 +1,21 @@ +############################################################################################## +# Values to be used for substitution by docker compose in compose.yml AND .*.env files +############################################################################################## + +APPLICATION_NAME=www-sthome + +DOCKERDIR=/mnt/SSD1/docker +MEDIADIR=/mnt/stpool1/NData1/Media + +STACKSDIR=${DOCKERDIR}/stacks/${APPLICATION_NAME} +DATAROOT=${DOCKERDIR}/data +DATADIR=${DATAROOT}/${APPLICATION_NAME} +SECRETSDIR=${STACKSDIR}/secrets +CERTSDIR=${DATAROOT}/traefik/certs + +SERVICE_PORT=80 +DOMAINNAME=sthome.org + +SUBDOMAIN1=www + + diff --git a/www-sthome/stacks/.nginx.env b/www-sthome/stacks/.nginx.env new file mode 100644 index 0000000..39aa757 --- /dev/null +++ b/www-sthome/stacks/.nginx.env @@ -0,0 +1,9 @@ + +PUID=3064 +PGID=3065 +TZ=Africa/Johannesburg + +NGINX_HOST=${SUBDOMAIN1}.${DOMAINNAME} +NGINX_PORT=80 + +NGINX_ENTRYPOINT_QUIET_LOGS=1 \ No newline at end of file diff --git a/www-sthome/stacks/compose.yml b/www-sthome/stacks/compose.yml new file mode 100644 index 0000000..edfb227 --- /dev/null +++ b/www-sthome/stacks/compose.yml @@ -0,0 +1,40 @@ +name: www-sthome + +networks: + traefik-net: + external: true + +services: + nginx: + image: nginx:latest + env_file: .nginx.env + # command: [nginx-debug, '-g', 'daemon off;'] + networks: + traefik-net: + aliases: ["${SUBDOMAIN1}"] + volumes: + - ${DATADIR}/appdata:/var/sites + - ${DATADIR}/config/sites-enabled:/etc/nginx/sites-enabled + - ${DATADIR}/config/templates:/etc/nginx/templates + - ${DATADIR}/config/nginx.conf:/etc/nginx/nginx.conf:ro + - ${DATADIR}/logs:/var/log/nginx + - ${MEDIADIR}/uploads:/uploads + restart: unless-stopped + labels: + - traefik.enable=true + - traefik.docker.network=traefik-net + #- "traefik.http.middlewares.${APPLICATION_NAME}-auth.basicauth.usersfile=/mnt/users/${APPLICATION_NAME}.txt" + - "traefik.http.services.${APPLICATION_NAME}-svc.loadbalancer.server.port=${SERVICE_PORT}" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.entrypoints=web" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.rule=Host(`${SUBDOMAIN1}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress-redirect@file" + - "traefik.http.routers.${APPLICATION_NAME}-rtr.service=${APPLICATION_NAME}-svc" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.entrypoints=websecure" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.rule=Host(`${SUBDOMAIN1}.${DOMAINNAME}`)&& PathPrefix(`/`)" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls=true" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.options=tls-options@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.tls.certresolver=solver-dns" + #- "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=${APPLICATION_NAME}-auth" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.middlewares=http-mw-rateLimit-secureHeaders-compress@file" + - "traefik.http.routers.${APPLICATION_NAME}-secure-rtr.service=${APPLICATION_NAME}-svc" + diff --git a/www-sthome/www-sthome_jm.txt b/www-sthome/www-sthome_jm.txt new file mode 100644 index 0000000..7be18ce --- /dev/null +++ b/www-sthome/www-sthome_jm.txt @@ -0,0 +1,40 @@ + +Create user and group +--------------------- +Credentials -> Local Users -> Add +Full Name: www-sthome +Username: www-sthome +Disable Password: +Create Home Directory: +Samba Authentication: +Save + +www-sthome UID: 3064 +www-sthome GID: 3065 + +Create datasets +--------------- +# In Truenas shell: +# list datasets +zfs list | grep -i "docker.*www-sthome" +# create following dataset if not present +zfs create SSD1/docker/data/www-sthome +zfs create SSD1/docker/data/www-sthome/config +zfs create SSD1/docker/data/www-sthome/appdata +zfs create SSD1/docker/data/www-sthome/logs +chown -R www-sthome:www-sthome /mnt/SSD1/docker/data/www-sthome + +Create stacks folder +--------------------- +mkdir -p /mnt/SSD1/docker/stacks/www-sthome + +Copy folder to docker stacks +---------------------------- +# In Windows cmd shell in www-sthome folder, enter: +./cp2nas 192.168.2.2 +# or +pscp -P 22 -r stacks/*.* root@192.168.2.2:/mnt/SSD1/docker/stacks/www-sthome/ +# This should copy stacks folder to /mnt/SSD1/docker/stacks/www-sthome \ No newline at end of file