init
PostgreSQL integration / tests (push) Has been cancelled

This commit is contained in:
ms
2026-11-09 13:15:48 +01:00
parent 4fb7613689
commit 2c1c48df0c
78 changed files with 2707 additions and 176 deletions
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail
# Local default DB. For external databases adapt connection options separately.
backup_dir="${1:?Usage: backup.sh /protected/backup/path}"
mkdir -p "$backup_dir"
chmod 700 "$backup_dir"
umask 077
partial="$(mktemp "$backup_dir/.dilib-backup-XXXXXX.partial")"
trap 'rm -f -- "$partial"' EXIT
pg_dump --format=custom --file="$partial" dilib_dashboard
pg_restore --list "$partial" >/dev/null
final="$backup_dir/dilib-dashboard-$(date -u +%Y%m%dT%H%M%SZ)-$$.dump"
mv -- "$partial" "$final"
printf 'Backup created: %s\n' "$final"
+25
View File
@@ -0,0 +1,25 @@
"""Configure a new deployment; never reads secrets from shell arguments."""
import argparse,os,re,secrets
from pathlib import Path
from dotenv import dotenv_values,set_key
def main():
parser=argparse.ArgumentParser()
parser.add_argument('--domain',required=True)
parser.add_argument('--env',default='/etc/dilib-dashboard/dashboard.env')
args=parser.parse_args()
if not re.fullmatch(r'[a-zA-Z0-9](?:[a-zA-Z0-9.-]*[a-zA-Z0-9])?',args.domain):
parser.error('Domain ohne Protokoll oder Port angeben')
path=Path(args.env)
if not path.is_file():parser.error('Env-Datei fehlt; zuerst install-central.sh ausführen')
current=dotenv_values(path)
# Updating the domain does not rotate existing secrets or change the database.
changes={'ALLOWED_HOSTS':args.domain+',127.0.0.1,localhost',
'CSRF_TRUSTED_ORIGINS':'https://'+args.domain}
for key in ('DJANGO_SECRET_KEY','NICEGUI_STORAGE_SECRET'):
if not current.get(key) or current[key].startswith('CHANGE_ME'):
changes[key]=secrets.token_urlsafe(64)
os.umask(0o077)
for key,value in changes.items():set_key(path,key,value,quote_mode='never')
print('Domain und gegebenenfalls Secrets gesetzt. DATABASE_URL und SMTP separat konfigurieren.')
if __name__=='__main__':main()
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
cd /opt/dilib-dashboard
[[ $EUID -eq 0 ]] || { echo 'Als root ausführen'; exit 1; }
# DATABASE_URL, Redis und Domain müssen vorher gesetzt sein.
bash scripts/manage-env.sh check
bash scripts/manage-env.sh migrate --noinput
bash scripts/manage-env.sh collectstatic --noinput
bash scripts/manage-env.sh doctor
systemctl enable --now dilib-api dilib-ui dilib-worker dilib-beat
sleep 3
bash scripts/manage-env.sh doctor --workers
echo 'Dienste gestartet. Admin anlegen: sudo bash scripts/manage-env.sh createsuperuser'
+6
View File
@@ -0,0 +1,6 @@
import secrets,sys
from pathlib import Path
p=Path(sys.argv[1]);text=p.read_text()
text=text.replace('DJANGO_SECRET_KEY=CHANGE_ME_GENERATE_WITH_SECRETS','DJANGO_SECRET_KEY='+secrets.token_urlsafe(64))
text=text.replace('NICEGUI_STORAGE_SECRET=CHANGE_ME_GENERATE_SEPARATELY','NICEGUI_STORAGE_SECRET='+secrets.token_urlsafe(64))
p.write_text(text)
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
[[ $EUID -eq 0 ]] || { echo 'Run as root on the monitored host.'; exit 1; }
[[ "$PWD" == /opt/dilib-dashboard ]] || { echo 'Extract project to /opt/dilib-dashboard first.'; exit 1; }
apt-get update
apt-get install -y python3 python3-venv
id dilib-agent >/dev/null 2>&1 || useradd --system --home /var/lib/dilib-agent --shell /usr/sbin/nologin dilib-agent
install -d -o dilib-agent -g dilib-agent -m 750 /var/lib/dilib-agent /var/lib/dilib-flower
install -d -o root -g dilib-agent -m 750 /etc/dilib-agent
python3 -m venv .venv-agent
.venv-agent/bin/pip install -r agent/requirements.txt
if [[ ! -f /etc/dilib-agent/agent.env ]]; then
install -m 640 -o root -g dilib-agent agent/.env.example /etc/dilib-agent/agent.env
fi
install -m 644 deploy/systemd/dilib-agent.service /etc/systemd/system/
systemctl daemon-reload
echo 'Configure agent.env and start: systemctl enable --now dilib-agent'
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
[[ $EUID -eq 0 ]] || { echo 'Run as root on the target Ubuntu server.'; exit 1; }
[[ "$PWD" == /opt/dilib-dashboard ]] || { echo 'Extract project to /opt/dilib-dashboard first.'; exit 1; }
apt-get update
apt-get install -y python3 python3-venv python3-dev build-essential libpq-dev postgresql postgresql-client redis-server
id dilib >/dev/null 2>&1 || useradd --system --home /var/lib/dilib-dashboard --shell /usr/sbin/nologin dilib
install -d -o dilib -g dilib -m 750 /var/lib/dilib-dashboard
install -d -m 750 -o root -g dilib /etc/dilib-dashboard
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
if [[ ! -f /etc/dilib-dashboard/dashboard.env ]]; then
install -m 640 -o root -g dilib .env.example /etc/dilib-dashboard/dashboard.env
.venv/bin/python scripts/generate-secrets.py /etc/dilib-dashboard/dashboard.env
fi
install -m 644 deploy/systemd/dilib-{api,ui,worker,beat,backup}.service /etc/systemd/system/
install -m 644 deploy/systemd/dilib-backup.timer /etc/systemd/system/
systemctl daemon-reload
printf '%s\n' 'Dependencies installed. Configure database, environment and HTTPS as described in docs/INSTALLATION.md. Services are not started yet.'
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
[[ $EUID -eq 0 && "$PWD" == /opt/dilib-dashboard ]] || { echo 'Als root in /opt/dilib-dashboard ausführen.'; exit 1; }
[[ -x .venv-agent/bin/python ]] || { echo 'Zuerst scripts/install-agent.sh ausführen.'; exit 1; }
.venv-agent/bin/pip install 'flower==2.2.0'
if [[ ! -e /etc/dilib-agent/flower.env ]]; then
install -m 640 -o root -g dilib-agent deploy/flower.env.example /etc/dilib-agent/flower.env
fi
install -m 644 deploy/systemd/dilib-flower.service /etc/systemd/system/
systemctl daemon-reload
echo 'Broker und FLOWER_BASIC_AUTH in /etc/dilib-agent/flower.env setzen.'
echo 'Dann: systemctl enable --now dilib-flower'
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
cd /opt/dilib-dashboard
# Environment loading uses python-dotenv, not shell eval.
exec /opt/dilib-dashboard/.venv/bin/python scripts/manage_env.py "$@"
+4
View File
@@ -0,0 +1,4 @@
import os,sys
from dotenv import load_dotenv
load_dotenv('/etc/dilib-dashboard/dashboard.env',override=True)
os.execv(sys.executable,[sys.executable,'manage.py',*sys.argv[1:]])
+13
View File
@@ -0,0 +1,13 @@
"""Generate HTTP-only reverse proxy config. Certbot configures TLS afterward."""
import argparse,re
from pathlib import Path
p=argparse.ArgumentParser()
p.add_argument('--domain',required=True)
p.add_argument('--server',choices=['nginx','apache'],default='nginx')
p.add_argument('--output',required=True)
a=p.parse_args()
if not re.fullmatch(r'[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?',a.domain):p.error('Invalid domain')
src=Path(__file__).resolve().parents[1]/'deploy'/f'{a.server}-http.conf'
target=Path(a.output)
with target.open('x') as f:f.write(src.read_text().replace('dashboard.example.com',a.domain))
print(target)