fixes
This commit is contained in:
@@ -15,7 +15,8 @@ localfile="$1"
|
||||
remotefile="$2"
|
||||
remotetmp_base="/var/tmp/4server"
|
||||
|
||||
while read -r host; do
|
||||
# Read hosts from file descriptor 3 to prevent ssh from consuming stdin
|
||||
while read -r host <&3; do
|
||||
host_env_file="$host_vars_dir/$host/$host.env"
|
||||
|
||||
if [ ! -f "$host_env_file" ]; then
|
||||
@@ -28,24 +29,19 @@ while read -r host; do
|
||||
source "$host_env_file"
|
||||
set +a
|
||||
|
||||
|
||||
NEBULA_KEY=$(<"$host_vars_dir/$host/$host.key")
|
||||
NEBULA_CRT=$(<"$host_vars_dir/$host/$host.crt")
|
||||
|
||||
SSH_PRIVATE=$(<"$host_vars_dir/$host/$host")
|
||||
SSH_PUBLIC=$(<"$host_vars_dir/$host/$host.pub")
|
||||
|
||||
content=$(<"$localfile")
|
||||
|
||||
for key in "${keys[@]}"; do
|
||||
value="${!key}" # indirect reference
|
||||
# Replace placeholder {{KEY}} with value using Bash's parameter expansion
|
||||
content="${content//\{\{$key\}\}/$value}"
|
||||
done
|
||||
|
||||
|
||||
|
||||
content=$(<"$localfile")
|
||||
|
||||
for key in "${keys[@]}"; do
|
||||
value="${!key}" # indirect reference
|
||||
# Replace placeholder {{KEY}} with value using Bash's parameter expansion
|
||||
content="${content//\{\{$key\}\}/$value}"
|
||||
done
|
||||
|
||||
# Copy content to remote temporary file
|
||||
remotetmp="${remotetmp_base}_${host}"
|
||||
@@ -55,7 +51,5 @@ done
|
||||
# Move temporary file to final location with doas
|
||||
ssh "$host" "doas mv '$remotetmp' '$remotefile'"
|
||||
|
||||
done < /app/host_vars/hosts
|
||||
|
||||
|
||||
done 3< /app/host_vars/hosts
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
rex "doas sqlite3 /4server/data/contracts.db <<'EOF'
|
||||
ALTER TABLE containers
|
||||
ALTER COLUMN contract DROP NOT NULL;
|
||||
rex "doas sqlite3 /4server/data/contracts.db <<EOF
|
||||
UPDATE containers
|
||||
SET affiliate = '{\"utm_source\":\"OD8N\",\"utm_medium\":\"direct\",\"utm_campaign\":\"none\"}';
|
||||
EOF"
|
||||
|
||||
16
app/sbin/api
16
app/sbin/api
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
from fastapi import FastAPI, HTTPException, Depends, Response
|
||||
from fastapi.security.api_key import APIKeyHeader
|
||||
from fastapi.responses import RedirectResponse
|
||||
from fastapi.responses import RedirectResponse, PlainTextResponse
|
||||
from pydantic import BaseModel
|
||||
import psutil
|
||||
import sqlite3
|
||||
@@ -14,6 +14,8 @@ import json
|
||||
import re
|
||||
from collections import deque
|
||||
import time
|
||||
from pathlib import Path
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
|
||||
@@ -277,6 +279,18 @@ def list_images():
|
||||
images = run_command(["docker", "images", "--format", "{{.Repository}}:{{.Tag}}"])
|
||||
return {"images": images.split("\n")}
|
||||
|
||||
@app.get("/system/cpu", dependencies=[Depends(verify_api_key)])
|
||||
def get_cpu_log():
|
||||
CPU_LOG_PATH = Path("/4server/data/log/cpu.log")
|
||||
if not CPU_LOG_PATH.exists():
|
||||
raise HTTPException(status_code=404, detail="CPU log file not found")
|
||||
|
||||
try:
|
||||
with CPU_LOG_PATH.open("r") as f:
|
||||
content = f.read()
|
||||
return PlainTextResponse(content)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error reading CPU log: {e}")
|
||||
|
||||
@app.get("/system/info", dependencies=[Depends(verify_api_key)])
|
||||
def get_system_info():
|
||||
|
||||
39
app/sbin/cpu
Executable file
39
app/sbin/cpu
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Log file
|
||||
OUTPUT="/4server/data/log/cpu_idle.log"
|
||||
|
||||
# Sampling interval in seconds
|
||||
INTERVAL=60
|
||||
|
||||
while true; do
|
||||
DATA="" # buffer to store idle samples
|
||||
|
||||
# Current date for the measurement period
|
||||
DATE=$(date "+%Y-%m-%d")
|
||||
|
||||
echo "Starting measurement for $DATE"
|
||||
|
||||
while [ "$(date +%H:%M)" != "23:45" ]; do
|
||||
# Get idle CPU percentage
|
||||
IDLE=$(mpstat 1 1 | awk '/Average/ {print $12}')
|
||||
|
||||
# Append to buffer
|
||||
DATA="$DATA$IDLE\n"
|
||||
|
||||
sleep $INTERVAL
|
||||
done
|
||||
|
||||
# Write all data to log file with date
|
||||
# Only one line per day: Date + space-separated idle samples
|
||||
echo -n "$DATE " >> "$OUTPUT"
|
||||
echo -e "$DATA" | tr '\n' ' ' >> "$OUTPUT"
|
||||
echo >> "$OUTPUT" # newline at the end
|
||||
echo "Measurement for $DATE written to $OUTPUT"
|
||||
|
||||
# Wait until 00:15 to start next day
|
||||
while [ "$(date +%H:%M)" != "00:15" ]; do
|
||||
sleep 30
|
||||
done
|
||||
done
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
# Load functions
|
||||
source /4server/sbin/ODOO_19/ODOO_19.lib
|
||||
|
||||
# Config variables
|
||||
UUID="${UUID:-default}"
|
||||
STAGING="${STAGING:-false}"
|
||||
if [[ -z "$UUID" ]]; then
|
||||
echo "Error: UUID not set. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
POSTGRES_HOST="${POSTGRES_HOST:-beedb}"
|
||||
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
||||
@@ -15,13 +15,16 @@ ODOO_DB_USER="${UUID}"
|
||||
export ODOO_DB_PASSWORD=$(echo "$SECRET" | jq -r '.psql')
|
||||
|
||||
BASEURL="${BASEURL:-/4server/data/$UUID}"
|
||||
BACKUPURL="/4backup/$UUID"
|
||||
|
||||
doas docker stop "$UUID"
|
||||
doas docker rm "$UUID"
|
||||
|
||||
if [ -n "${UUID:-}" ]; then
|
||||
echo "Removing directory: $BASEURL"
|
||||
doas rm -rf "$BASEURL"
|
||||
#doas rm -rf "$BASEURL"
|
||||
echo "Removing backup directory $BACKUPURL"
|
||||
#doas rm -rf $BACKUPURL
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,30 @@ if [[ -z "$UUID" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
get_container_status() {
|
||||
local uuid="$1"
|
||||
# Get the container ID or name matching the UUID
|
||||
CONTAINER_ID=$(docker ps -a --filter "name=$uuid" --format "{{.ID}}")
|
||||
if [[ -z "$CONTAINER_ID" ]]; then
|
||||
echo "not_found"
|
||||
return
|
||||
fi
|
||||
|
||||
STATUS=$(docker inspect -f '{{.State.Status}}' "$CONTAINER_ID")
|
||||
echo "$STATUS"
|
||||
}
|
||||
|
||||
# Check if container exists
|
||||
STATUS=$(get_container_status "$UUID")
|
||||
if [[ "$STATUS" == "running" ]]; then
|
||||
echo "Container $UUID is still running. Aborting deletion."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
get_contract_info
|
||||
|
||||
# Extract the second part of UUID (split by "-")
|
||||
@@ -34,3 +58,11 @@ case "$SECOND_PART" in
|
||||
;;
|
||||
esac
|
||||
|
||||
sqlite3 "/4server/data/contracts.db" <<SQL
|
||||
DELETE FROM containers WHERE UUID='$UUID';
|
||||
SQL
|
||||
|
||||
|
||||
|
||||
echo "Container $UUID successfully nuked."
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ doas docker run -d --name "$UUID" \
|
||||
--label "traefik.http.routers.$UUID.service=$UUID" \
|
||||
docker.odoo4projects.com/4projects/odoo_17:$BRANCH
|
||||
|
||||
doas docker exec "$UUID" rm /var/lib/odoo/.local/share/Odoo/filestore
|
||||
doas 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
|
||||
|
||||
@@ -33,6 +33,7 @@ docker run -d \
|
||||
-e NODE_ENV=production \
|
||||
-e WEBHOOK_URL="https://${UUID}.odoo4projects.com/" \
|
||||
-e GENERIC_TIMEZONE="UTC-3" \
|
||||
-e N8N_CUSTOM_EXTENSIONS="/usr/local/share/n8n/custom" \
|
||||
-v "/4server/data/${UUID}/n8n:/home/node/.n8n" \
|
||||
-v "/4server/data/${UUID}/data:/data" \
|
||||
--label "traefik.enable=true" \
|
||||
@@ -42,7 +43,6 @@ docker run -d \
|
||||
--label "traefik.http.routers.${UUID}.tls.certresolver=production" \
|
||||
--label "traefik.http.services.${UUID}.loadbalancer.server.port=5678" \
|
||||
--network 4server_4projects \
|
||||
n8nio/n8n:latest
|
||||
|
||||
docker.odoo4projects.com/4projects/n8n:release
|
||||
|
||||
echo "Started $1"
|
||||
|
||||
@@ -15,6 +15,20 @@ if [[ -z "$UUID" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
DOMAIN_FILE="/4server/data/$UUID/etc/domain"
|
||||
DB_FILE="/4server/data/contracts.db"
|
||||
if [ -f "$DOMAIN_FILE" ]; then
|
||||
DOMAINS=$(paste -sd "," "$DOMAIN_FILE")
|
||||
sqlite3 "$DB_FILE" <<SQL
|
||||
UPDATE containers
|
||||
SET domains='$DOMAINS'
|
||||
WHERE UUID='$UUID';
|
||||
SQL
|
||||
fi
|
||||
|
||||
|
||||
|
||||
get_contract_info
|
||||
|
||||
# Extract the second part of UUID (split by "-")
|
||||
|
||||
6
app/sbin/stopContainer
Executable file
6
app/sbin/stopContainer
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
exec > /4server/data/log/stopContainer.log 2>&1
|
||||
echo "$(date '+%Y-%m-%d %H:%M') Stop container $1"
|
||||
|
||||
docker stop $1
|
||||
|
||||
17
app/templates/init.d/cpu
Executable file
17
app/templates/init.d/cpu
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/sbin/openrc-run
|
||||
# OpenRC service for /4server/sbin/cpu
|
||||
|
||||
name="cpu"
|
||||
description="Logs cpu usage"
|
||||
|
||||
command="/4server/sbin/cpu"
|
||||
command_background="yes"
|
||||
pidfile="/run/cpu.pid"
|
||||
output_log="/4server/data/log/cpu.log"
|
||||
error_log="/4server/data/log/cpu.log"
|
||||
|
||||
depend() {
|
||||
need localmount
|
||||
after bootmisc
|
||||
}
|
||||
|
||||
@@ -68,6 +68,13 @@ rex doas chown root:root /etc/init.d/cleanTmp
|
||||
rex doas rc-update add cleanTmp default
|
||||
rex doas rc-service cleanTmp restart
|
||||
|
||||
#INSTALL cpu service
|
||||
template templates/init.d/cpu /etc/init.d/cpu
|
||||
rex doas chmod 0755 /etc/init.d/cpu
|
||||
rex doas chown root:root /etc/init.d/cpu
|
||||
rex doas rc-update add cpu default
|
||||
rex doas rc-service cpu restart
|
||||
|
||||
### Infrastructure
|
||||
##### Docker
|
||||
rex doas rc-service docker start
|
||||
|
||||
Binary file not shown.
@@ -4,6 +4,7 @@ set -euo pipefail
|
||||
VAULT_FILE="/app/vault/host_vars.img"
|
||||
MAPPER_NAME="host_vars_crypt"
|
||||
MOUNT_POINT="/app/host_vars"
|
||||
LOOP_DEVICE="/dev/loop50"
|
||||
|
||||
mkdir -p "$MOUNT_POINT"
|
||||
|
||||
@@ -13,19 +14,36 @@ if cryptsetup status "$MAPPER_NAME" >/dev/null 2>&1; then
|
||||
cryptsetup close "$MAPPER_NAME"
|
||||
fi
|
||||
|
||||
# Open
|
||||
# Detach loop device if already in use
|
||||
if losetup "$LOOP_DEVICE" >/dev/null 2>&1; then
|
||||
echo "Detaching stale loop device $LOOP_DEVICE..."
|
||||
losetup -d "$LOOP_DEVICE"
|
||||
fi
|
||||
|
||||
# Create loop device if missing
|
||||
if [ ! -e "$LOOP_DEVICE" ]; then
|
||||
echo "Creating loop device $LOOP_DEVICE..."
|
||||
mknod "$LOOP_DEVICE" b 7 50
|
||||
chmod 660 "$LOOP_DEVICE"
|
||||
fi
|
||||
|
||||
# Attach vault file to loop device
|
||||
echo "Attaching $VAULT_FILE to $LOOP_DEVICE..."
|
||||
losetup "$LOOP_DEVICE" "$VAULT_FILE"
|
||||
|
||||
# Open encrypted volume
|
||||
echo "Opening encrypted volume..."
|
||||
cryptsetup open "$VAULT_FILE" "$MAPPER_NAME"
|
||||
cryptsetup open "$LOOP_DEVICE" "$MAPPER_NAME"
|
||||
|
||||
# Format if needed
|
||||
if ! blkid /dev/mapper/"$MAPPER_NAME" >/dev/null 2>&1; then
|
||||
if ! blkid "/dev/mapper/$MAPPER_NAME" >/dev/null 2>&1; then
|
||||
echo "No filesystem found, creating ext4..."
|
||||
mkfs.ext4 /dev/mapper/"$MAPPER_NAME"
|
||||
mkfs.ext4 "/dev/mapper/$MAPPER_NAME"
|
||||
fi
|
||||
|
||||
# Mount
|
||||
echo "Mounting at $MOUNT_POINT..."
|
||||
mount /dev/mapper/"$MAPPER_NAME" "$MOUNT_POINT"
|
||||
mount "/dev/mapper/$MAPPER_NAME" "$MOUNT_POINT"
|
||||
|
||||
echo "Vault is mounted at $MOUNT_POINT"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user