infrastructure: move .env + CrowdSec key into org with noweb references

This commit is contained in:
root
2026-06-06 12:42:48 -04:00
parent 54827a4256
commit c12910d0f1
2 changed files with 258 additions and 21 deletions

View File

@@ -230,6 +230,11 @@ Why each piece:
Shared middleware used by all routers. Defined once here, referenced by name Shared middleware used by all routers. Defined once here, referenced by name
in every router block. in every router block.
#+NAME: crowdsec_key
#+BEGIN_SRC sh :results raw :exports none
echo "Xvx3UTjAdThkqtNuVhciWzEOJuBZoWH58KE+E7C3L6I"
#+END_SRC
#+BEGIN_SRC yaml :tangle /docker/appdata/traefik/dynamic.yaml #+BEGIN_SRC yaml :tangle /docker/appdata/traefik/dynamic.yaml
http: http:
middlewares: middlewares:
@@ -261,7 +266,7 @@ http:
crowdsec-bouncer-traefik-plugin: crowdsec-bouncer-traefik-plugin:
enabled: "true" enabled: "true"
crowdsecMode: live crowdsecMode: live
crowdsecLapiKey: __CROWDSEC_LAPI_KEY__ crowdsecLapiKey: <<crowdsec_key()>>
crowdsecLapiHost: crowdsec:8080 crowdsecLapiHost: crowdsec:8080
crowdsecLapiScheme: http crowdsecLapiScheme: http
updateFrequencySec: 5 updateFrequencySec: 5
@@ -1529,3 +1534,252 @@ http:
#+END_SRC #+END_SRC
service: http://10.10.10.29:8082 service: http://10.10.10.29:8082
middleware: tunnel-headers@file middleware: tunnel-headers@file
* Environment Variables
Tangled to /docker/compose/.env. The CROWDSEC_LAPI_KEY is a noweb reference
to the shared crowdsec_key block, so it stays in sync with dynamic.yaml.
#+BEGIN_SRC dotenv :tangle /docker/compose/.env
## Auto-generated from infrastructure.org -- do not edit directly.
## Edit infrastructure.org and tangle to update.
#################################################################################
#################################################################################
#################################################################################
##
## Docker Compose Environment Variable file for Jellyfin / *ARR Media Stack
##
## Update any of the environment variables below as required.
##
## It is highly recommended Linux users set up a "docker" user, so the
## applications can access the local filesystem with this user's access
## privileges. Use PUID / PGID to map user access between the Docker apps
## and local filesystem.
##
## The MediaStack Guide is located at https://MediaStack.Guide
##
#################################################################################
#################################################################################
#################################################################################
###################################################
## add /dev/net/tun to LXC
## https://pve.proxmox.com/wiki/OpenVPN_in_LXC
###################################################
# Name of the project in Docker
COMPOSE_PROJECT_NAME=docker-production
COMPOSE_BAKE=true
# This is the network subnet which will be used inside the docker "media_network", change as required.
# LOCAL_SUBNET is your home network and is needed so the VPN client allows access to your home computers.
DOCKER_SUBNET=172.28.10.0/24
DOCKER_GATEWAY=172.28.10.1
LOCAL_SUBNET=10.10.10.0/24 # This is the IP Subnet used on your home network
LOCAL_DOCKER_IP=10.10.10.201 # This is the IP Address of your Docker computer
# Each of the "*ARR" applications have been configured so the theme can be changed to your needs.
# Refer to Theme Park for more info / options: https://docs.theme-park.dev/theme-options/aquamarine/
TP_THEME=nord
# If you intend to use Plex as your Media Server, then enter your Plex Claim
# information below, to link this Plex Media Server to your Plex account
# Access Plex claim at: https://account.plex.tv/en/claim
PLEX_CLAIM=claim-1234567890abcdef
# These are the folders on your local host computer / NAS running docker, they MUST exist
# and have correct permissions for PUID and PGUI prior to running the docker compose.
#
# Use the commands in the Guide to create all the sub-folders in each of these folders.
# Host Data Folders - Will accept Linux, Windows, NAS folders.
# Make sure these folders exists before running the "docker compose" command.
FOLDER_FOR_MEDIA=/library
# <-- Update for your folders - Synology Example: /volume1/media
FOLDER_FOR_DATA=/docker/appdata
# <-- Update for your folders - Synology Example: /volume1/docker/appdata
FOLDER_FOR_MORE=/more
# File access, date and time details for the containers / applications to use.
# Run "sudo id docker" on host computer to find PUID / PGID and update these to suit.
PUID=1000
PGID=1000
UMASK=0002
TIMEZONE=America/New_York
# Update your own Internet VPN provide details below
# Online documentation: https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers
VPN_TYPE=openvpn
VPN_SERVICE_PROVIDER=privado
VPN_USERNAME=nhmpxamumlrj
VPN_PASSWORD=ulm8kRtJdmFLAum3tEb
# You MUST provide at least one entry to the SERVER variables below, that supports your VPN provider's settings.
# If you want to add more than one entry per line, use comma separated values: "one,two,three" etc...
SERVER_COUNTRIES=Netherlands
SERVER_REGIONS=
SERVER_CITIES=
SERVER_HOSTNAMES=
SERVER_CATEGORIES=
# Fill in this item ONLY if you're using a custom OpenVPN configuration
# Should be inside gluetun data folder - Example: /gluetun/custom-openvpn.conf
# You can then edit it inside the FOLDER_FOR_DATA location for gluetun.
OPENVPN_CUSTOM_CONFIG=
GLUETUN_CONTROL_PORT=8320
# Fill in these items ONLY if you change VPN_TYPE to "wireguard"
VPN_ENDPOINT_IP=
VPN_ENDPOINT_PORT=
WIREGUARD_PUBLIC_KEY=
WIREGUARD_PRIVATE_KEY=
WIREGUARD_PRESHARED_KEY=
WIREGUARD_ADDRESSES=
# These are the ports used to access each of the applications in your web browser.
# You can safely change these if you need, but they can't conflict with other active ports.
QBIT_PORT=6881
FLARESOLVERR_PORT=8191
TDARR_SERVER_PORT=8266
# WebUI ports for internal access to applications
WEBUI_PORT_AUDIOBOOKSHELF=13378
WEBUI_PORT_AUTHENTIK=6080
WEBUI_PORT_BAZARR=6767
WEBUI_PORT_CHROMIUM=3650
WEBUI_PORT_DDNS_UPDATER=8310
WEBUI_PORT_FILEBOT=5454
WEBUI_PORT_GUACAMOLE=9200
WEBUI_PORT_GRAFANA=3800
WEBUI_PORT_HEADPLANE=3500
WEBUI_PORT_HEIMDALL=2080
WEBUI_PORT_HOMARR=3200
WEBUI_PORT_HOMEPAGE=3000
WEBUI_PORT_HUNTARR=9705
WEBUI_PORT_JELLYFIN=8096
WEBUI_PORT_JELLYSEERR=5055
WEBUI_PORT_LAZYLIBRARIAN=5299
WEBUI_PORT_LIDARR=8686
WEBUI_PORT_MYLAR=8090
WEBUI_PORT_PLEX=32400
WEBUI_PORT_PORTAINER=9000
WEBUI_PORT_PROMETHEUS=9090
WEBUI_PORT_PROWLARR=9696
WEBUI_PORT_QBITTORRENT=8200
WEBUI_PORT_RADARR=7878
WEBUI_PORT_READARR=8787
WEBUI_PORT_SABNZBD=8100
WEBUI_PORT_SONARR=8989
WEBUI_PORT_STASH=7777
WEBUI_PORT_TDARR=8265
WEBUI_PORT_TRAEFIK=8080
WEBUI_PORT_WHISPARR=6969
CHROMIUM_START_PAGE="https://github.com/geekau/mediastack/"
# Traefik is configured for Reverse Proxy. Set your Internet gateway to redirect incoming ports 80 and 443
# to the ports used below (using Docker IP Address), and they will be translated back to 80 and 443 by Traefik.
# Change these port numbers if you have conflicting services running on the Docker host computer.
# If ports 80 and 443 are already used, then adjust and redirect incoming ports to 5080 and 5443, or similar.
REVERSE_PROXY_PORT_HTTP=80
REVERSE_PROXY_PORT_HTTPS=443
# Traefik Configuration
# Your CloudFlare Account Email Address
CLOUDFLARE_EMAIL=gharbeia@riseup.net
# Your CloudFlare Registered Domain Name
CLOUDFLARE_DNS_ZONE=gharbeia.net
# Your CloudFlare Read / Write API Token
CLOUDFLARE_DNS_API_TOKEN=cfut_unDIAx2wqL2tm8OmcZWpzrQTRPPA5FlenlVfeL7Nf94c360b
# Headscale / Headplane / Tailscale VPN Wireguard Mesh Networking
# These port settings are only to change the internal port due to conflicts, Headscale, Tailscale and Headplane will
# all function normally using the default ports as they are routed through Traefik reverse proxy.
CONNECT_PORT_HEADSCALE=4080
METRICS_PORT_HEADSCALE=4090
CROWDSEC_PORT=9080
METRICS_PORT_TRAEFIK=8082
INTERNAL_PORT_TRAEFIK=8083
METRICS_PORT_UNPACKERR=5656
# The Tailscale Docker container is configured as an exit node inside your home network, so traffic can route securely
# across the Internet, and break out behind your home gateway / router.
# sudo docker exec -it headscale headscale users create exit-node
# sudo docker exec -it headscale headscale --user exit-node preauthkeys create
# NOTE: Headscale must be running before the commands can be executed, then update authkey below and restart Tailscale.
TAILSCALE_AUTHKEY=57332c4f29ef77727d3310a34d903ae83ccae4c6392460fc
# Connect to the following address to complete the initial setup of Authentik after first deployment:
# http://<DOCKER-IP-ADDRESS>:6080/if/flow/initial-setup/
# echo AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')
AUTHENTIK_SECRET_KEY=P)'K"7sF#>Ia+m-8jOyn6\]6S
AUTHENTIK_VERSION=2025.4.1
AUTHENTIK_ERROR_REPORTING__ENABLED=true
POSTGRESQL_PORT=5432
VALKEY_PORT=6379
# echo POSTGRESQL_PASSWORD=$(openssl rand -base64 60 | tr -d '\n')
POSTGRESQL_PASSWORD=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
POSTGRESQL_USERNAME=library-postgresql
AUTHENTIK_DATABASE=library-authentik
GUACAMOLE_DATABASE=library-guacamole
GUACD_PORT=4822
# SMTP Host Emails are sent to
EMAIL_SERVER_HOST=smtp.fastmail.com
EMAIL_SERVER_PORT=25
# Optionally authenticate (don't add quotation marks to your password)
EMAIL_ADDRESS=amr@gharbeia.net
EMAIL_PASSWORD=3a58334x8a9r8x7e
# Use StartTLS
EMAIL_TLS=true
# Use SSL - StartTLS and SSL can't both be true
EMAIL_SSL=false
# Email address authentik will send from, should have a correct @domain.name
EMAIL_SENDER=authentik@gharbeia.net
#### Gitea
GITEA__database__DB_TYPE=sqlite3
GITEA__database__PATH=/data/gitea/gitea.db
GITEA__server__DOMAIN=10.10.10.201
GITEA__server__HTTP_PORT=3001
GITEA__server__SSH_PORT=2222
GITEA__server__ROOT_URL=http://10.10.10.201:3000/
GITEA__security__INSTALL_LOCK=true
GITEA__service__DISABLE_REGISTRATION=false
# ports:
# - "127.0.0.1:3000:3000"
# - "127.0.0.1:2222:22"
# Cloudflare Tunnel token for cloudflared
TUNNEL_TOKEN=eyJhIjoiYWY0Y2RkYWM0N2UwMDFmZDZkNWMyMGFjNmRkZGFkM2QiLCJ0IjoiYzI5Mjk1YzUtOTQ2YS00ZGRmLWJkZmUtN2VhZmNkNzRmYWEzIiwicyI6Ik5qQm1aVEV4TjJFdFptRTFPUzAwTjJWbUxUZ3pORE10TURKa1lqRXhNMlptT1RVNCJ9
# Tube Archivist
TA_USERNAME=admin
TA_PASSWORD=DsO1BPfMEXMJROG9NlgEslOd
WEBUI_PORT_AUDIOMUSE=8005
# khaledfahmy.org
KHALEDFAHMY_DB_ROOT_PASSWORD=kf_root_ch4ng3_m3
KHALEDFAHMY_DB_PASSWORD=t1)~Bt~1uwmwe?pq}sZj%b!t8
# Nancy Okail (WordPress)
NANCYOKAIL_DB_ROOT_PASSWORD=changeme_placeholder
NANCYOKAIL_DB_PASSWORD=changeme_placeholder
# Rim Naguib (WordPress)
RIMNAGUIB_DB_ROOT_PASSWORD=changeme_placeholder
RIMNAGUIB_DB_PASSWORD=changeme_placeholder
# Fishere (WordPress)
FISHERE_DB_ROOT_PASSWORD=changeme_placeholder
FISHERE_DB_PASSWORD=changeme_placeholder
CROWDSEC_LAPI_KEY=<<crowdsec_key()>>
#+END_SRC

23
tangle-deploy.sh Normal file → Executable file
View File

@@ -1,4 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# tangle-deploy — Tangle infrastructure.org and restart affected services
GITEA_URL='ssh://git@git.gharbeia.net:2222/amr/infrastructure.git' GITEA_URL='ssh://git@git.gharbeia.net:2222/amr/infrastructure.git'
REPO_DIR="${1:-/docker/compose/infrastructure}" REPO_DIR="${1:-/docker/compose/infrastructure}"
ORG_FILE="${REPO_DIR}/infrastructure.org" ORG_FILE="${REPO_DIR}/infrastructure.org"
@@ -16,15 +17,8 @@ fi
echo "=== Tangling $ORG_FILE ===" echo "=== Tangling $ORG_FILE ==="
emacs --batch -Q --load /usr/share/emacs/28.2/lisp/org/org-loaddefs.el \ emacs --batch -Q --load /usr/share/emacs/28.2/lisp/org/org-loaddefs.el \
--eval "(require 'org)" \ --eval "(require 'org)" \
--eval "(org-babel-tangle-file \"$ORG_FILE\")" 2>&1 --eval "(require 'ob-shell)" \
# Substitute env vars in tangled files --eval '(let ((org-confirm-babel-evaluate nil)) (org-babel-tangle-file "'"$ORG_FILE"'"))' 2>&1
# Read key from .env directly (avoid sourcing due to quoting issues in other vars)
CROWDSEC_LAPI_KEY=$(grep ^CROWDSEC_LAPI_KEY /docker/compose/.env | cut -d= -f2-)
if [ -z "$CROWDSEC_LAPI_KEY" ] || [ "$CROWDSEC_LAPI_KEY" = "__CROWDSEC_LAPI_KEY__" ]; then
echo "ERROR: CROWDSEC_LAPI_KEY not set or still a placeholder in .env!"
exit 1
fi
sed -i "s|__CROWDSEC_LAPI_KEY__|${CROWDSEC_LAPI_KEY}|g" /docker/appdata/traefik/dynamic.yaml
echo "=== Restarting services ===" echo "=== Restarting services ==="
cd /docker/compose cd /docker/compose
if [ -f /docker/appdata/traefik/traefik.yaml ] || \ if [ -f /docker/appdata/traefik/traefik.yaml ] || \
@@ -33,17 +27,6 @@ if [ -f /docker/appdata/traefik/traefik.yaml ] || \
[ -f /docker/appdata/traefik/dynamic.yaml ]; then [ -f /docker/appdata/traefik/dynamic.yaml ]; then
echo 'Traefik config changed -- restarting...' echo 'Traefik config changed -- restarting...'
docker compose up -d traefik docker compose up -d traefik
# Verify CrowdSec bouncer is working after restart
sleep 2
STATUS=$(docker exec traefik wget -q -O /dev/null -S http://traefik:8081/application/o/authorize/ --header="Host: auth.gharbeia.net" 2>&1 | head -1 | awk '{print $2}')
if [ "$STATUS" = "403" ]; then
echo "WARNING: auth.gharbeia.net still returns 403 after deploy!"
echo " CrowdSec bouncer may have a bad API key."
echo " Run: docker exec crowdsec cscli bouncers add traefik-bouncer"
echo " Then update CROWDSEC_LAPI_KEY in /docker/compose/.env and re-deploy."
else
echo "OK: auth.gharbeia.net returns $STATUS (expected: 400)"
fi
fi fi
if [ -f /docker/compose/docker-compose.yaml ]; then if [ -f /docker/compose/docker-compose.yaml ]; then
echo 'Docker compose changed -- restarting all services' echo 'Docker compose changed -- restarting all services'