import db

This commit is contained in:
Oliver
2025-11-24 16:30:29 -03:00
parent b3e7909c90
commit 38873facc0
12 changed files with 193 additions and 39 deletions

View File

@@ -24,3 +24,12 @@ Host mumbai
User 4server User 4server
IdentityFile /app/host_vars/mumbai/mumbai IdentityFile /app/host_vars/mumbai/mumbai
Host meppel
Hostname 192.168.9.21
User 4server
IdentityFile /app/host_vars/meppel/meppel
Host saopaulo
Hostname 192.168.9.11
User 4server
IdentityFile /app/host_vars/saopaulo/saopaulo

View File

@@ -8,3 +8,9 @@
192.168.9.16 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCXNdN2lYWg9k3r5B9QISWCAWvAzzDj/aO5EeYPimDcz383Qliq0xW+FjJvgw2fY/Aoljwd6pGY3pJPN1aM3i4Qxt22S6emsFkGm89/GOdEu9ZkB+ln0fL8uPJTdjQklkhGb8YIF4aD8OMkMNXn7Ale+TiJJuWWmh7UAQITM5EqX1Wq+uAM/2ixpKo3dQU8L6pzeGi5yQUzHB3eyckSnFjCrSS/hW6lsKyhoaSYn+cAiuhbWEwP4lv9um6Cl2rLZYcysJTTs1DP7gJL3eyytnQ83R8MEX5/qY2zSVFCaNPguF7hlC7MgdR90naqlzm40XzYXHloDIg92+kGZGdR6jcKy7QasHuQLeXXJEk63jl64IJwRJPNnrVGszEDwIz0nBzVX/Yot2R/uAjhJRdR5d9tlZbMILkng6I/BVdJhqnJzuBottZpfu0qaBakIecDbLiJeU+AbAQffzWesyAmlHaLLLCHgwLdNaVjCltx6/RebF8HRRO82sdRE8Js6dSAXZ0= 192.168.9.16 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCXNdN2lYWg9k3r5B9QISWCAWvAzzDj/aO5EeYPimDcz383Qliq0xW+FjJvgw2fY/Aoljwd6pGY3pJPN1aM3i4Qxt22S6emsFkGm89/GOdEu9ZkB+ln0fL8uPJTdjQklkhGb8YIF4aD8OMkMNXn7Ale+TiJJuWWmh7UAQITM5EqX1Wq+uAM/2ixpKo3dQU8L6pzeGi5yQUzHB3eyckSnFjCrSS/hW6lsKyhoaSYn+cAiuhbWEwP4lv9um6Cl2rLZYcysJTTs1DP7gJL3eyytnQ83R8MEX5/qY2zSVFCaNPguF7hlC7MgdR90naqlzm40XzYXHloDIg92+kGZGdR6jcKy7QasHuQLeXXJEk63jl64IJwRJPNnrVGszEDwIz0nBzVX/Yot2R/uAjhJRdR5d9tlZbMILkng6I/BVdJhqnJzuBottZpfu0qaBakIecDbLiJeU+AbAQffzWesyAmlHaLLLCHgwLdNaVjCltx6/RebF8HRRO82sdRE8Js6dSAXZ0=
192.168.9.16 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLpXVmQVbrhdfbrTHINQ2lZCxLxgrWbIDoNoxRR7EuqI5qNr2LQhqmTVZpNUIvj7PhdGPN4hry9jMfC39Dwa7Eo= 192.168.9.16 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLpXVmQVbrhdfbrTHINQ2lZCxLxgrWbIDoNoxRR7EuqI5qNr2LQhqmTVZpNUIvj7PhdGPN4hry9jMfC39Dwa7Eo=
192.168.9.11 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFbAGYglyMYT/IfX9G4n9GhbPf+8T7TyVin/DfP3eKgb
192.168.9.11 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCthnkPJKC1Ij/Fc4fTRubcV8xDSKJ4UrlUYgZ+lO2AZYKhefVZOaDkizqWbjf9c4dqAAEX1lqgDwr3UwEw6hukLLhherCU6tn3Q/nmOQsbKrEGG+kJXnzCi1jYsH4UNQB8Xl18eaLhGZosqCfEVK3LHw2/nMsxLfbrw61qf9Z7/haQOJU2M2W9X3U/yEk4sOCoxguJIoNJ0JZB+X3xO2TXKLCKuaWpckbmHAVuL0c4u0ZfYqF3lCxWLj/iI5SKD/YqajohaVBaoJkmtIkLuuSSFe5gJb22htMgKXoQ0TcxxAvTnHwa92sVSMx7Lp1zQ5RGzN+Dw99FL4HyR4KDPlmVpGPZbNp0LnnggQ0SBmT6F3KarNZLzSW6w2foBkl9XjTEBUjb5cHXK8jq7nEUK26TgirngSAFg7y44NWta6whRX0+/wCanlvgQ1BNYGf4vcw5P+Q8MoGOdepF7b8gQiUn/KhtmnQem/Q1//xDt9MOJkmjBemG9KIso/gqtJkHeps=
192.168.9.11 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDc6J024++J25z2ZMXQ3Vim+mLVIVs+cZngv8DmtEDfrT/Ptl7+F2IqXRNcZuq1YTjEZO8eQg27iIemPoPT3xa8=
192.168.9.21 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMFuf87ngDaF8D0kzVzzB953ji6ptg/V9t+WPac+DAjO
192.168.9.21 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtexcutExMflSRPJOwGPuZx49c+ZUMoElNPNntXONOuVZ8jM+zzA/4s+HCj+RWdHMnarLcNJjwRZRq7JWruqmr1EN9eNmvu13cLCKZr6Ape1gt8VmMhvQ9nA7eMx3UdvnWgXjLCfJy+BKh2XVAneM5lOSPMcyQlcACrLQVkse9EKhxhV5nEjXKYxSNetIPK9PxglXznpC8IpuWlXnDH2R8vDhdvBmBFTKOjN5Wa+GrMfElWeQOjyCpNcMVYohvV87VN6FxHQTADFTm2CKy/W7pnM8rI55ZbBIMfvLyhpM+vtFh1sJlIZSFnn+ytMUImNEAgBDI3fCpwZ99zeLViGhQJlBkdCUI+JJK9XJjpcOMNydeWh142RGU6juPuSLOZPqKNc3BpZYgPY0vMDgDWgT9AcYup3rAJ/UnUnhsxiT2h/gx7+t/j9xg01BQF5S6mezaueuavHCh9MvAzXiJXR8zanhl/Hh9BKgIAFrZh71CzP/PYG33BKCe9DXA09aJrf8=
192.168.9.21 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGlzLZWNjSaDuDd4e66LoBizY5j+QCsifIIxkvX4CrzP/AqAgWDEEgT+pAXBFkNJlBR6TDFJ0bIdwZTbcq8/72E=

View File

@@ -1 +1 @@
dev meppel

47
app/sbin/ODOO_19/dbVersion Executable file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env python3
import csv
import sys
import zipfile
if len(sys.argv) < 2:
print("Usage: python3 check_odoo_version.py <dump.zip>")
sys.exit(1)
zip_path = sys.argv[1]
base_version = None
with zipfile.ZipFile(zip_path, 'r') as z:
# Assume there is only one .sql file in the zip
sql_files = [f for f in z.namelist() if f.endswith('.sql')]
if not sql_files:
print("No .sql file found in the zip.")
sys.exit(1)
sql_file_name = sql_files[0]
with z.open(sql_file_name, 'r') as f:
# Decode bytes to string
lines = (line.decode('utf-8') for line in f)
# Skip lines until COPY command
for line in lines:
if line.startswith("COPY public.ir_module_module"):
break
# Read the COPY data until the terminator '\.'
reader = csv.reader(lines, delimiter='\t', quotechar='"', escapechar='\\')
for row in reader:
if row == ['\\.']: # End of COPY
break
if len(row) < 12:
continue
module_name = row[7].strip() # 8th column = name
if module_name == "base":
base_version = row[11].strip() # 12th column = latest_version
break
if base_version:
print(base_version.split(".")[0])
else:
print("Base module not found in dump.")

32
app/sbin/ODOO_19/import Normal file
View File

@@ -0,0 +1,32 @@
#!/bin/bash
# Create the tmp directory if it doesn't exist
mkdir -p /4server/tmp/
# Save original stdout
exec 3>&1
# Redirect all other output to log
exec > /4server/data/log/importDb.log 2>&1
echo "$(date '+%Y-%m-%d %H:%M') Import file $1"
# Generate random 8-digit filename
RANDOM_FILE="/4server/tmp/$(printf "%08d" $((RANDOM % 100000000))).zip"
# Download file from Google Drive using gdown
gdown "$1" -O "$RANDOM_FILE"
# Execute dbVersion on the downloaded file and capture output
VERSION=$(/4server/sbin/ODOO_19/dbVersion "$RANDOM_FILE")
# Output JSON to original stdout
cat <<EOF >&3
{
"version":"$VERSION",
"file":"$RANDOM_FILE"
}
EOF
# Close saved stdout
exec 3>&-

View File

@@ -24,7 +24,7 @@ from pathlib import Path
DB_PATH = "/4server/data/contracts.db" DB_PATH = "/4server/data/contracts.db"
BIN_PATH = "/4server/sbin" BIN_PATH = "/4server/sbin"
API_KEY = os.getenv("API_KEY", "your-secret-api-key") API_KEY = os.getenv("API_KEY", "your-secret-api-key")
VERSION = "API: 0.0.7" VERSION = "API: 0.0.8"
# ---------------------- FastAPI App ---------------------- # ---------------------- FastAPI App ----------------------
app = FastAPI() app = FastAPI()
@@ -124,6 +124,13 @@ class CommandRequest(BaseModel):
uuid: str uuid: str
method: int method: int
class ImportRequest(BaseModel):
filename: str
class MoveRequest(BaseModel):
source: str
destination: str
# ---------------------- Routes ---------------------- # ---------------------- Routes ----------------------
@app.get("/", include_in_schema=False) @app.get("/", include_in_schema=False)
@@ -362,6 +369,7 @@ async def get_odoo_log_summary(uuid: str):
re.compile(r"ERROR"), # Errors re.compile(r"ERROR"), # Errors
re.compile(r"WARNING"), # Warnings re.compile(r"WARNING"), # Warnings
re.compile(r"Traceback"), # Tracebacks re.compile(r"Traceback"), # Tracebacks
re.compile(r"Error"),
] ]
def is_important_line(line: str) -> bool: def is_important_line(line: str) -> bool:
@@ -396,6 +404,32 @@ async def get_odoo_log_summary(uuid: str):
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"Error reading log files: {e}") raise HTTPException(status_code=500, detail=f"Error reading log files: {e}")
# ------------------------ BACKUP HANDLING -------------------------------------
@app.post("/backup/import", dependencies=[Depends(verify_api_key)])
def backup_import(request: ImportRequest):
if not request.filename:
raise HTTPException(status_code=400, detail="Filename is required")
command = [f"{BIN_PATH}/ODOO_19/import", request.filename]
output = run_command(command)
return {"message": output}
@app.post("/backup/move", dependencies=[Depends(verify_api_key)])
def backup_move(request: MoveRequest):
if not request.source or not request.destination:
raise HTTPException(status_code=400, detail="Source and destination are required")
if not os.path.exists(request.source):
raise HTTPException(status_code=404, detail="Source file does not exist")
# Use shell command to move the file
command = ["mv", request.source, request.destination] # Linux/macOS
# For Windows, use: command = ["move", request.source, request.destination]
output = run_command(command)
return {"message": f"Moved {request.source} to {request.destination}", "output": output}
# ---------------------- Entry Point ---------------------- # ---------------------- Entry Point ----------------------
if __name__ == "__main__": if __name__ == "__main__":
print(VERSION) print(VERSION)

View File

@@ -58,24 +58,30 @@ RULE="${RULE# || }"
DOMAIN_LABEL="traefik.http.routers.$UUID.rule=$RULE" DOMAIN_LABEL="traefik.http.routers.$UUID.rule=$RULE"
echo "[DEBUG] Final Traefik label: $DOMAIN_LABEL" echo "[DEBUG] Final Traefik label: $DOMAIN_LABEL"
doas docker exec "$UUID" mkdir -p /var/lib/odoo/.local/share/Odoo/ docker exec "$UUID" mkdir -p /var/lib/odoo/.local/share/Odoo/
doas docker exec "$UUID" ln -s /home/odoo/.local/share/Odoo/filestore /var/lib/odoo/.local/share/Odoo/filestore docker exec "$UUID" ln -s /home/odoo/.local/share/Odoo/filestore /var/lib/odoo/.local/share/Odoo/filestore
doas find "$BASEURL" -type d -exec chmod 777 {} \; find "$BASEURL" -type d -exec chmod 777 {} \;
PORT=$((CONTAINERDBID + 2200)) PORT=$((CONTAINERDBID + 2200))
echo "PORT $PORT" echo "PORT $PORT"
chmod 777 $ETC_DIR mkdir -p ${ETC_DIR}
chmod 77 $ETC_DIR/gitpath echo "GITPATH ${ETC_DIR}gitpath"
echo "git clone \"ssh://git@${UUID}.odoo4projects.com:${PORT}/git-server/repos/odoo.git\"" > ${ETC_DIR}/gitpath touch ${ETC_DIR}gitpath
echo "GIIIT $ETC_DIR $PORT"
doas docker stop "$UUID" 2>/dev/null mkdir -p ${GIT_DIR}keys
doas docker rm "$UUID" 2>/dev/null touch ${GIT_DIR}keys/id_rsa.pub
echo "git clone \"ssh://git@${UUID}.odoo4projects.com:${PORT}/git-server/repos/odoo.git\"" > "${ETC_DIR}/gitpath"
docker stop "$UUID" 2>/dev/null
docker rm "$UUID" 2>/dev/null
EXTRA_DOCKER_PARAMETER="" EXTRA_DOCKER_PARAMETER=""
doas docker run -d --name "$UUID" \ docker run -d --name "$UUID" \
--network 4server_4projects \ --network 4server_4projects \
--restart=always \ --restart=always \
$EXTRA_DOCKER_PARAMETER \ $EXTRA_DOCKER_PARAMETER \
@@ -107,12 +113,15 @@ doas docker run -d --name "$UUID" \
--label "traefik.http.routers.$UUID.service=$UUID" \ --label "traefik.http.routers.$UUID.service=$UUID" \
docker.odoo4projects.com/4projects/odoo_17:$BRANCH docker.odoo4projects.com/4projects/odoo_17:$BRANCH
doas docker exec "$UUID" rm /var/lib/odoo/.local/share/Odoo/filestore docker exec "$UUID" mkdir -p /var/lib/odoo/.local/share/Odoo
doas docker exec "$UUID" ln -s /home/odoo/.local/share/Odoo/filestore /var/lib/odoo/.local/share/Odoo/filestore docker exec "$UUID" rm -rf /var/lib/odoo/.local/share/Odoo/filestore
docker exec "$UUID" ln -s /home/odoo/.local/share/Odoo/filestore /var/lib/odoo/.local/share/Odoo/filestore
doas docker exec $UUID chown -R odoo:odoo /home/odoo/.local
doas docker exec $UUID chown -R odoo:odoo /mnt/* docker exec $UUID chown -R odoo:odoo /home/odoo/.local
doas docker exec $UUID chown -R odoo:odoo /var/lib/odoo/.local/share/Odoo docker exec $UUID chown -R odoo:odoo /var/lib/odoo/.local/share/Odoo
docker exec $UUID chown -R odoo:odoo /mnt/*
docker exec $UUID chown odoo:odoo /git-server/keys/id_rsa.pub
check_and_create_db check_and_create_db

View File

@@ -58,24 +58,30 @@ RULE="${RULE# || }"
DOMAIN_LABEL="traefik.http.routers.$UUID.rule=$RULE" DOMAIN_LABEL="traefik.http.routers.$UUID.rule=$RULE"
echo "[DEBUG] Final Traefik label: $DOMAIN_LABEL" echo "[DEBUG] Final Traefik label: $DOMAIN_LABEL"
doas docker exec "$UUID" mkdir -p /var/lib/odoo/.local/share/Odoo/ docker exec "$UUID" mkdir -p /var/lib/odoo/.local/share/Odoo/
doas docker exec "$UUID" ln -s /home/odoo/.local/share/Odoo/filestore /var/lib/odoo/.local/share/Odoo/filestore docker exec "$UUID" ln -s /home/odoo/.local/share/Odoo/filestore /var/lib/odoo/.local/share/Odoo/filestore
doas find "$BASEURL" -type d -exec chmod 777 {} \; find "$BASEURL" -type d -exec chmod 777 {} \;
PORT=$((CONTAINERDBID + 2200)) PORT=$((CONTAINERDBID + 2200))
echo "PORT $PORT" echo "PORT $PORT"
chmod 777 $ETC_DIR mkdir -p ${ETC_DIR}
chmod 77 $ETC_DIR/gitpath echo "GITPATH ${ETC_DIR}gitpath"
echo "git clone \"ssh://git@${UUID}.odoo4projects.com:${PORT}/git-server/repos/odoo.git\"" > ${ETC_DIR}/gitpath touch ${ETC_DIR}gitpath
echo "GIIIT $ETC_DIR $PORT"
doas docker stop "$UUID" 2>/dev/null mkdir -p ${GIT_DIR}keys
doas docker rm "$UUID" 2>/dev/null touch ${GIT_DIR}keys/id_rsa.pub
echo "git clone \"ssh://git@${UUID}.odoo4projects.com:${PORT}/git-server/repos/odoo.git\"" > "${ETC_DIR}/gitpath"
docker stop "$UUID" 2>/dev/null
docker rm "$UUID" 2>/dev/null
EXTRA_DOCKER_PARAMETER="" EXTRA_DOCKER_PARAMETER=""
doas docker run -d --name "$UUID" \ docker run -d --name "$UUID" \
--network 4server_4projects \ --network 4server_4projects \
--restart=always \ --restart=always \
$EXTRA_DOCKER_PARAMETER \ $EXTRA_DOCKER_PARAMETER \
@@ -107,10 +113,15 @@ doas docker run -d --name "$UUID" \
--label "traefik.http.routers.$UUID.service=$UUID" \ --label "traefik.http.routers.$UUID.service=$UUID" \
docker.odoo4projects.com/4projects/odoo_18:$BRANCH docker.odoo4projects.com/4projects/odoo_18:$BRANCH
docker exec "$UUID" mkdir -p /var/lib/odoo/.local/share/Odoo
docker exec "$UUID" rm -rf /var/lib/odoo/.local/share/Odoo/filestore
docker exec "$UUID" ln -s /home/odoo/.local/share/Odoo/filestore /var/lib/odoo/.local/share/Odoo/filestore
doas docker exec $UUID chown -R odoo:odoo /home/odoo/.local
doas docker exec $UUID chown -R odoo:odoo /mnt/*
docker exec $UUID chown -R odoo:odoo /home/odoo/.local
docker exec $UUID chown -R odoo:odoo /var/lib/odoo/.local/share/Odoo
docker exec $UUID chown -R odoo:odoo /mnt/*
docker exec $UUID chown odoo:odoo /git-server/keys/id_rsa.pub
check_and_create_db check_and_create_db

View File

@@ -60,22 +60,26 @@ echo "[DEBUG] Final Traefik label: $DOMAIN_LABEL"
doas find "$BASEURL" -type d -exec chmod 777 {} \; find "$BASEURL" -type d -exec chmod 777 {} \;
PORT=$((CONTAINERDBID + 2200)) PORT=$((CONTAINERDBID + 2200))
echo "PORT $PORT" echo "PORT $PORT"
mkdir -p ${ETC_DIR} mkdir -p ${ETC_DIR}
echo "GITPATH ${ETC_DIR}gitpath" echo "GITPATH ${ETC_DIR}gitpath"
touch ${ETC_DIR}gitpath touch ${ETC_DIR}gitpath
mkdir -p ${GIT_DIR}keys
touch ${GIT_DIR}keys/id_rsa.pub
echo "git clone \"ssh://git@${UUID}.odoo4projects.com:${PORT}/git-server/repos/odoo.git\"" > "${ETC_DIR}/gitpath" echo "git clone \"ssh://git@${UUID}.odoo4projects.com:${PORT}/git-server/repos/odoo.git\"" > "${ETC_DIR}/gitpath"
doas docker stop "$UUID" 2>/dev/null docker stop "$UUID" 2>/dev/null
doas docker rm "$UUID" 2>/dev/null docker rm "$UUID" 2>/dev/null
EXTRA_DOCKER_PARAMETER="" EXTRA_DOCKER_PARAMETER=""
doas docker run -d --name "$UUID" \ docker run -d --name "$UUID" \
--network 4server_4projects \ --network 4server_4projects \
--restart=always \ --restart=always \
$EXTRA_DOCKER_PARAMETER \ $EXTRA_DOCKER_PARAMETER \
@@ -108,9 +112,9 @@ doas docker run -d --name "$UUID" \
docker.odoo4projects.com/4projects/odoo_19:$BRANCH docker.odoo4projects.com/4projects/odoo_19:$BRANCH
doas docker exec $UUID chown -R odoo:odoo /home/odoo/.local docker exec $UUID chown -R odoo:odoo /home/odoo/.local
doas docker exec $UUID chown -R odoo:odoo /mnt/* docker exec $UUID chown -R odoo:odoo /mnt/*
docker exec $UUID chown odoo:odoo /git-server/keys/id_rsa.pub
chmod 777 /4server/data/$UUID/cc
check_and_create_db check_and_create_db

View File

@@ -7,10 +7,11 @@ HOSTNAME=$(hostname)
mkdir -p /4server/data/${UUID}/n8n mkdir -p /4server/data/${UUID}/n8n
mkdir -p /4server/data/${UUID}/data mkdir -p /4server/data/${UUID}/data
mkdir -p /4server/data/${UUID}/backup
chmod 777 /4server/data/${UUID}/n8n chmod 777 /4server/data/${UUID}/n8n
chmod 777 /4server/data/${UUID}/data chmod 777 /4server/data/${UUID}/data
chmod 777 /4server/data/${UUID}/backup
# Stop the container if it exists # Stop the container if it exists
if docker ps -a --format '{{.Names}}' | grep -q "^${UUID}$"; then if docker ps -a --format '{{.Names}}' | grep -q "^${UUID}$"; then
@@ -35,6 +36,7 @@ docker run -d \
-e GENERIC_TIMEZONE="UTC-3" \ -e GENERIC_TIMEZONE="UTC-3" \
-e N8N_CUSTOM_EXTENSIONS="/usr/local/share/n8n/custom" \ -e N8N_CUSTOM_EXTENSIONS="/usr/local/share/n8n/custom" \
-v "/4server/data/${UUID}/n8n:/home/node/.n8n" \ -v "/4server/data/${UUID}/n8n:/home/node/.n8n" \
-v "/4server/data/${UUID}/backup:/data" \
-v "/4server/data/${UUID}/backup:/backup" \ -v "/4server/data/${UUID}/backup:/backup" \
--label "traefik.enable=true" \ --label "traefik.enable=true" \
--label "traefik.http.routers.${UUID}.rule=Host(\`${UUID}.odoo4projects.com\`)" \ --label "traefik.http.routers.${UUID}.rule=Host(\`${UUID}.odoo4projects.com\`)" \

View File

@@ -27,7 +27,7 @@ template templates/repositories /etc/apk/repositories
rex "doas apk update && doas apk upgrade" rex "doas apk update && doas apk upgrade"
rex doas apk add iperf linux-lts openssh ufw python3 build-base python3-dev linux-headers py3-pip gcc g++ musl-dev libffi-dev make jq rsync mc vim docker docker-compose htop linux-lts sqlite bash postgresql16-client rex doas apk add iperf linux-lts openssh ufw python3 build-base python3-dev linux-headers py3-pip gcc g++ musl-dev libffi-dev make jq rsync mc vim docker docker-compose htop linux-lts sqlite bash postgresql16-client
rex doas pip install --root-user-action ignore --break-system-packages --no-cache-dir "uvicorn[standard]" fastapi pydantic psutil rex doas pip install --root-user-action ignore --break-system-packages --no-cache-dir "uvicorn[standard]" fastapi pydantic psutil gdown
### own bins ### own bins
echo "Running prsync ./sbin" echo "Running prsync ./sbin"

Binary file not shown.