Adding function to manage parameters

This commit is contained in:
2025-08-20 15:22:29 +00:00
parent e1263416d9
commit 06e7699960

View File

@@ -1,485 +1,126 @@
#!/bin/bash
# This script is used to update your version of apxtri. It checks the code version in the package.json file. If the version is different,
# the script is triggered. It is launched via a curl request to the apxtri Gitea server, linked to a crontab.
set -euo pipefail
# Launching command for any environment:
# sudo apt install wget -y && sudo wget -O launch.sh https://gitea.ndda.fr/apxtri/apxtri/raw/branch/main/setup/launch.sh && sudo chmod +x launch.sh && ./launch.sh
# ==== CHARGER LES VARIABLES DE launch.sh ====
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../.env"
#If you have already an install, add "--clean" at the end of the command above.
if [[ -f "$ENV_FILE" ]]; then
set -a
source "$ENV_FILE"
set +a
else
echo "[ERROR].env introuvable !" >&2
exit 1
fi
set -eEuo pipefail
trap 'err_handler $LINENO $?' ERR
# ==== NOUVELLE FONCTION POUR LES TRIBUS ====
handle_tribes() {
local tribes_string="$1"
IFS=',' read -ra TRIBES <<< "$tribes_string"
# ==== CONFIG ====
URL_REPO="https://gitea.ndda.fr/apxtri"
REPO_APXTRI="$URL_REPO/apxtri.git"
REPO_OBJECTS="$URL_REPO/objects.git"
DATAPATH="/var/lib/apxtowns"
NODEPATH="/opt/apxtowns"
LOGPATH="/var/log/apxtowns"
NATION="ants"
TOWN="farm"
APXTRI_USER="apxtri"
NODE_VERSION="lts"
MAINJS="startapx"
URLBACKUP="https://app1.smatchit.io"
APIPORT="3000" # Default API port
# ==== LOGGING ====
sudo touch /var/log/apxtri_install.log
sudo chown "$USER":"$USER" /var/log/apxtri_install.log
exec > >(tee -i /var/log/apxtri_install.log)
exec 2>&1
# ==== ERROR HANDLER ====
err_handler() {
local lineno="$1"
local code="$2"
if [[ "$code" -eq 99 ]]; then
echo "[INFO] Installation voluntarily stopped at line $lineno (exit 99)."
exit 99
fi
echo "[ERROR] Failure at line $lineno (code $code). Starting cleanup..."
# On ne lance pas le nettoyage complet ici pour permettre de débugger l'erreur
# et de ne pas effacer l'installation d'apxtri si le problème est avec Caddy.
# Le script s'arrêtera, mais l'utilisateur pourra vérifier les logs
# et relancer le script après avoir résolu le problème manuellement.
echo "[INFO] The script has stopped due to an error. Please check the logs above for details."
exit "$code"
}
# ==== CLEANING ====
cleaning() {
echo "[CLEAN] Starting cleanup..."
# Kill any lingering process on the API port
echo "[CLEAN] Checking for lingering processes on API port ${APIPORT}..."
sudo fuser -k "${APIPORT}/tcp" 2>/dev/null || true
# Arrêter et désactiver les services si existants
sudo systemctl stop apxtri 2>/dev/null || true
sudo systemctl disable apxtri 2>/dev/null || true
sudo systemctl stop caddy 2>/dev/null || true
sudo systemctl disable caddy 2>/dev/null || true
# Supprimer les fichiers de service
sudo rm -f /etc/systemd/system/apxtri.service
sudo rm -f /etc/systemd/system/caddy.service.d/override.conf 2>/dev/null || true
sudo systemctl daemon-reload
# Nettoyage spécifique à apxtri
CURRENT_USER=${SUDO_USER:-$(whoami)}
if sudo -u "$APXTRI_USER" crontab -l 2>/dev/null | grep -Fq "backup.sh"; then
sudo -u "$APXTRI_USER" crontab -l 2>/dev/null | grep -v "backup.sh" | sudo -u "$APXTRI_USER" crontab -
fi
if id -nG "$CURRENT_USER" | grep -qw "$APXTRI_USER"; then
sudo gpasswd -d "$CURRENT_USER" "$APXTRI_USER" || true
fi
if id "$APXTRI_USER" &>/dev/null; then
sudo userdel -r "$APXTRI_USER" 2>/dev/null || true
fi
if getent group "$APXTRI_USER" &>/dev/null; then
sudo groupdel "$APXTRI_USER" 2>/dev/null || true
fi
sudo rm -rf "$DATAPATH" "$NODEPATH" "$LOGPATH" /etc/apxtowns
sudo sed -i "/admin.apxtri.$TOWN.$NATION/d" /etc/hosts || true
# Nettoyage complet de Caddy
if command -v caddy &>/dev/null; then
echo "[CLEAN] Removing Caddy and its configuration..."
sudo apt-get purge -y caddy
sudo rm -rf /etc/caddy /var/lib/caddy /usr/share/caddy
sudo rm -f /etc/apt/sources.list.d/caddy-stable.list
sudo rm -f /usr/share/keyrings/caddy-stable-archive-keyring.gpg
fi
# Nettoyage des permissions et des fichiers sudoers
sudo rm -f /etc/sudoers.d/apxtri-caddy
sudo rm -rf /run/caddy
echo "[CLEAN] Cleanup complete."
}
# ==== ARGUMENT PARSING ====
# Initialize mode to empty to trigger interactive prompt if not set by arguments
mode=""
clean_install=false
# Function to display usage
usage() {
echo "Usage: $0 [--mode <dev|prod>] [--nation <name>] [--town <name>] [--datapath <path>] [--nodepath <path>] [--apiport <port>] [--clean] [--help]"
echo " --mode Installation mode. If not set, prompts interactively."
echo " --nation Set the nation name (default: 'ants'). Overridden by 'dev' mode to 'test'."
echo " --town Set the town name (default: 'farm')."
echo " --datapath Set the data path (default: '/var/lib/apxtowns')."
echo " --nodepath Set the node path (default: '/opt/apxtowns')."
echo " --apiport Set the API port (default: '3000')."
echo " --clean Force removal of any existing installation before proceeding."
echo " --help Display this help message."
if [[ ${#TRIBES[@]} -eq 0 ]]; then
echo "[ERROR] Aucun nom de tribu fourni." >&2
exit 1
fi
echo "📦 Téléchargement des tribus : ${TRIBES[*]}"
for tribe in "${TRIBES[@]}"; do
tribe=$(echo "$tribe" | xargs) # trim espaces
if [[ -z "$tribe" ]]; then
continue
fi
echo "➡️ Clonage de la tribu '$tribe'..."
# Lien factice pour linstant :
git clone "https://fake.repo.url/${tribe}.git" "$NODEPATH/$TOWN-$NATION/$tribe" || true
done
}
# Parse command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--mode)
if [[ -z "$2" || "$2" == --* ]]; then echo "Error: Missing value for --mode" >&2; usage; fi
mode="$2"
shift 2
;;
--nation)
if [[ -z "$2" || "$2" == --* ]]; then echo "Error: Missing value for --nation" >&2; usage; fi
NATION="$2"
shift 2
;;
--town)
if [[ -z "$2" || "$2" == --* ]]; then echo "Error: Missing value for --town" >&2; usage; fi
TOWN="$2"
shift 2
;;
--datapath)
if [[ -z "$2" || "$2" == --* ]]; then echo "Error: Missing value for --datapath" >&2; usage; fi
DATAPATH="$2"
shift 2
;;
--nodepath)
if [[ -z "$2" || "$2" == --* ]]; then echo "Error: Missing value for --nodepath" >&2; usage; fi
NODEPATH="$2"
shift 2
;;
--apiport)
if [[ -z "$2" || "$2" == --* ]]; then echo "Error: Missing value for --apiport" >&2; usage; fi
APIPORT="$2"
shift 2
;;
--clean)
clean_install=true
shift 1
;;
--help|-h)
usage
;;
*)
echo "Error: Unknown option $1" >&2
usage
;;
esac
done
# ==== VÉRIFIER LES PARAMÈTRES ====
if [[ $# -ge 1 ]]; then
handle_tribes "$1"
exit 0
fi
# ---
# ==== CHECK EXISTING INSTALLATION ====
if [ -d "$NODEPATH/$TOWN-$NATION/apxtri" ] || [ -d "$DATAPATH" ] || { [ "$(id -u 2>/dev/null || echo)" -eq 0 ] && id "$APXTRI_USER" &>/dev/null; }; then
if [ "$clean_install" = true ]; then
echo "Existing installation detected and --clean flag was provided."
echo "Removing existing installation..."
cleaning
else
echo "[WARN] Existing apxtri installation detected."
echo "To perform a clean re-installation, please run the script again with the --clean flag."
echo "Example: $0 --mode dev --clean"
echo "Aborting installation to prevent accidental data loss."
exit 99 # Using the custom exit code for voluntary stop
# ==== FICHIERS PACKAGE.JSON ====
LOCAL_PACKAGE="$NODEPATH/$TOWN-$NATION/apxtri/package.json"
REMOTE_PACKAGE_URL="$URL_REPO/apxtri/raw/branch/main/package.json"
if [[ ! -f "$LOCAL_PACKAGE" ]]; then
echo "[ERROR] Fichier $LOCAL_PACKAGE introuvable !" >&2
exit 1
fi
# ==== EXTRAIRE LES VERSIONS ====
LOCAL_VERSION=$(grep -oP '"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+' "$LOCAL_PACKAGE")
REMOTE_VERSION=$(curl -fsSL "$REMOTE_PACKAGE_URL" | grep -oP '"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+')
if [[ -z "$LOCAL_VERSION" || -z "$REMOTE_VERSION" ]]; then
echo "[ERROR] Impossible de lire les versions locale/distante" >&2
exit 1
fi
echo "$DATE 🔍 Version locale : $LOCAL_VERSION Version distante: $REMOTE_VERSION"
# ==== FONCTION COMPARAISON SEMVER ====
compare_versions() {
local IFS=.
local ver1=($1) ver2=($2)
# compléter avec des zéros si une partie manque
for ((i=${#ver1[@]}; i<3; i++)); do ver1[i]=0; done
for ((i=${#ver2[@]}; i<3; i++)); do ver2[i]=0; done
# comparer major, minor, patch dans l'ordre
for i in 0 1 2; do
if ((10#${ver1[i]} < 10#${ver2[i]})); then
echo "lt-$i" # version locale < distante à ce niveau
return
elif ((10#${ver1[i]} > 10#${ver2[i]})); then
echo "gt-$i" # version locale > distante
return
fi
fi
done
# ---
# ==== SET DEV/PROD MODE ====
# If mode was not set by arguments, ask interactively
if [[ -z "$mode" ]]; then
while true; do
read -p "Install apXtri in dev or prod mode? [dev/prod]: " interactive_mode
case "$interactive_mode" in
dev|prod)
mode="$interactive_mode"
break
;;
*) echo "Please choose dev or prod" ;;
esac
done
fi
echo "eq" # exactement égal
}
# Process the final mode value
case "$mode" in
dev)
echo "Development mode selected"
NATION="test"
MAINJS="dev"
;;
prod)
echo "Production mode selected"
# Keep default NATION and MAINJS
;;
*)
echo "Error: Invalid mode '$mode'. Please use 'dev' or 'prod'." >&2
exit 1
;;
RESULT=$(compare_versions "$LOCAL_VERSION" "$REMOTE_VERSION")
case "$RESULT" in
eq)
echo "$DATE ✅ Aucune mise à jour nécessaire.($LOCAL_VERSION -> $REMOTE_VERSION)"
exit 0
;;
lt-0)
echo "$DATE ⚠️ New major version. Check your README and your code before update.($LOCAL_VERSION -> $REMOTE_VERSION)."
exit 0
;;
lt-1|lt-2)
echo "$DATE ⬆️ Minor version detected.($LOCAL_VERSION -> $REMOTE_VERSION). Updating..."
;;
gt-*)
echo "$DATE ⚠️ Local version ($LOCAL_VERSION) est plus récente que la distante ($REMOTE_VERSION)."
exit 0
;;
esac
echo "---"
echo "Final configuration:"
echo " Mode: $mode"
echo " Nation: $NATION"
echo " Town: $TOWN"
echo " Data Path: $DATAPATH"
echo " Node Path: $NODEPATH"
echo "---"
# ---
# ==== INSTALL TOOLS ====
sudo apt update --fix-missing
sudo apt install -y curl git gnupg jq build-essential locales vim libcap2-bin p7zip-full p7zip-rar unzip psmisc
sudo locale-gen en_US.UTF-8 fr_FR.UTF-8
sudo update-locale LANG=en_US.UTF-8
# ---
# ==== CHECK CADDY ====
if ! command -v caddy &>/dev/null; then
echo "Installing Caddy..."
# Créer le répertoire avec les bonnes permissions
sudo mkdir -p /usr/share/keyrings
sudo chmod 755 /usr/share/keyrings
# Télécharger la clé GPG avec curl vers un fichier temporaire
sudo curl -fsSL https://dl.cloudsmith.io/public/caddy/stable/gpg.key -o /tmp/caddy-key.gpg
# Convertir la clé et la placer avec les bonnes permissions
sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg /tmp/caddy-key.gpg
sudo chmod 644 /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo rm -f /tmp/caddy-key.gpg
# Ajouter le dépôt
echo "deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main" | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install -y caddy
else
echo "Caddy already installed."
fi
# ---
# ==== HOSTS ====
if ! grep -q "admin.apxtri.$TOWN.$NATION" /etc/hosts; then
echo "127.0.0.1 admin.apxtri.$TOWN.$NATION" | sudo tee -a /etc/hosts
else
echo "admin.apxtri.$TOWN.$NATION already in /etc/hosts"
fi
# ---
# ==== CREATE USER ====
if ! id "$APXTRI_USER" &>/dev/null; then
echo "Creating system user $APXTRI_USER..."
sudo useradd --system --no-create-home --shell /usr/sbin/nologin "$APXTRI_USER"
echo "$APXTRI_USER:malayme42" | sudo chpasswd
else
echo "User $APXTRI_USER already exists."
fi
# ---
# ==== CONFIGURE CADDY SERVICE ====
# Ensure Caddy uses its default service file by removing any overrides
echo "Ensuring Caddy uses default service configuration..."
sudo rm -f /etc/systemd/system/caddy.service.d/override.conf
sudo systemctl daemon-reload
# Utiliser '|| true' pour que le script continue même si Caddy échoue à démarrer
sudo systemctl start caddy || true
# ---
# ==== ADD USERS TO APXTRI GROUP ====
# Add current user to manage files easily
CURRENT_USER=${SUDO_USER:-$(whoami)}
sudo usermod -aG "$APXTRI_USER" "$CURRENT_USER"
# Add caddy user to allow it to read the web files it needs to serve
sudo usermod -aG "$APXTRI_USER" caddy
# ---
# ==== DIRECTORIES ====
sudo mkdir -p "$NODEPATH/$TOWN-$NATION" "$LOGPATH" "$DATAPATH/data/apxtri/logs" "$DATAPATH/data/apxtri/tmp" "$NODEPATH/$TOWN-$NATION/apxtri/tmp"
sudo chown -R "$APXTRI_USER:$APXTRI_USER" "$DATAPATH" "$NODEPATH" "$LOGPATH" "$NODEPATH/$TOWN-$NATION/apxtri/tmp"
sudo chmod -R g+rwX "$NODEPATH" "$DATAPATH"
# ---
# ==== SET GROUP INHERITANCE FOR WWWS ====
# Apply the 'setgid' bit recursively ONLY to 'wwws' directories.
# This ensures that any new file/directory created within any 'wwws' folder
# will automatically inherit the 'apxtri' group, allowing Caddy to read it.
echo "Configuring group permission inheritance for Caddy on wwws directories..."
sudo find "$DATAPATH" -type d -name "wwws" -exec chmod g+s {} +
# After setting setgid, we re-apply group read/execute permissions recursively
# to ensure all existing content is accessible by the 'caddy' user.
echo "Ensuring Caddy has read access to all existing wwws content..."
sudo find "$DATAPATH" -type d -name "wwws" -exec chmod -R g+rX {} +
# The sudoers rule for Caddy is no longer needed with the API approach.
# echo "$APXTRI_USER ALL=(ALL) NOPASSWD: /bin/systemctl reload caddy" | sudo tee /etc/sudoers.d/apxtri-caddy
# sudo chmod 440 /etc/sudoers.d/apxtri-caddy
# ---
# ==== CLONE REPOS ====
# Clone objects repo first
sudo -u "$APXTRI_USER" mkdir -p "$DATAPATH/data/apxtri/objects"
sudo -u "$APXTRI_USER" git clone "$REPO_OBJECTS" "$DATAPATH/data/apxtri/objects" || {
echo "[WARN] Objects repository clone failed or already exists, continuing..."
}
# Download and extract setup files
ZIP_URL="$URL_REPO/apxtri/raw/branch/main/setup/apxtri.objects.setup.zip"
ZIP_FILE="$DATAPATH/data/apxtri/apxtri.objects.setup.zip"
# Run wget from a temp directory to avoid permission errors with wget-log
sudo -u "$APXTRI_USER" bash -c "cd /tmp && wget -O '$ZIP_FILE' '$ZIP_URL'" || {
echo "[WARN] Failed to download setup zip, continuing..."
}
sudo -u "$APXTRI_USER" unzip -q -o "$ZIP_FILE" -d "$DATAPATH/data/apxtri/objects" || {
echo "[WARN] Failed to unzip setup files, continuing..."
}
sudo rm -f "$ZIP_FILE"
# Clone main repo (force clean clone if directory exists)
if [ -d "$NODEPATH/$TOWN-$NATION/apxtri" ]; then
echo "[INFO] Removing existing apxtri directory for clean clone..."
sudo rm -rf "$NODEPATH/$TOWN-$NATION/apxtri"
fi
sudo -u "$APXTRI_USER" git clone "$REPO_APXTRI" "$NODEPATH/$TOWN-$NATION/apxtri"
# ---
# ==== ENV FILE ====
sudo tee "$NODEPATH/$TOWN-$NATION/apxtri/.env" > /dev/null <<EOL
URL_REPO="$URL_REPO"
VERSION="1.0.0"
MODE="$mode"
TOWN="$TOWN"
NATION="$NATION"
UBUNTU="server"
ETCCONF="/etc/apxtowns/apxtowns"
DATAPATH="$DATAPATH"
NODEPATH="$NODEPATH"
LOGPATH="$LOGPATH"
APIPORT="$APIPORT"
ACTIVELOG=apxtri,isAuthenticated,checkHeaders,Odmdb,Pagans,Persons,Wwws,Trackings,Notifications
##debug,info,warn,error, debug and info will be shown only if a name.js is in ACTIVELOG to help to be focus in debugging
##LOG_LEVEL=debug
EXPOSEDHEADERS="xdays,xalias,xlang,xtribe,xapp,xuuid"
SOCKETPORT="3001"
BACKENDURL="localhost"
CADDYAPIURL="http://localhost:2019"
##CADDYAPIURL="unix//run/caddy/admin.sock"
EOL
sudo chown "$APXTRI_USER:$APXTRI_USER" "$NODEPATH/$TOWN-$NATION/apxtri/.env"
# ---
# ==== NVM + NODE INSTALL ====
npm_config_cache="${DATAPATH:-/tmp}/.npm"
sudo mkdir -p "$npm_config_cache"
sudo chown -R "$APXTRI_USER:$APXTRI_USER" "$npm_config_cache"
NVM_DIR="$NODEPATH/$TOWN-$NATION/apxtri/.nvm"
sudo -u "$APXTRI_USER" HOME="$NODEPATH/$TOWN-$NATION/apxtri" DATAPATH="$DATAPATH" NODE_VERSION="$NODE_VERSION" npm_config_cache="$npm_config_cache" NVM_DIR="$NVM_DIR" bash <<EOF
set -euo pipefail
if [ ! -d "$NVM_DIR" ]; then
echo "Installing NVM..."
git clone https://github.com/nvm-sh/nvm.git "$NVM_DIR"
cd "$NVM_DIR"
git checkout master
else
echo "NVM already installed in $NVM_DIR"
fi
# Ensure the nvm script is executable
chmod +x "$NVM_DIR/nvm.sh"
export NVM_DIR="$NVM_DIR"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install --lts
nvm alias default 'lts/*'
nvm use default
npm install -g npm@latest
# ==== MISE A JOUR ====
echo "⚡ Mise à jour en cours..."
sudo apt update && sudo apt upgrade -y
cd "$NODEPATH/$TOWN-$NATION/apxtri"
if [ -f package.json ]; then
echo "Installing npm dependencies..."
npm install
fi
EOF
git pull origin main
npm install
# ---
# ==== SYSTEMD SERVICE FOR PROD ONLY ====
if [[ "$mode" == "prod" ]]; then
SERVICE_PATH="/etc/systemd/system/apxtri.service"
echo "Creating systemd service for apxtri..."
sudo tee "$SERVICE_PATH" > /dev/null <<EOF
[Unit]
Description=apXtri production service
After=network.target
[Service]
Type=simple
User=$APXTRI_USER
Group=$APXTRI_USER
WorkingDirectory=$NODEPATH/$TOWN-$NATION/apxtri
EnvironmentFile=$NODEPATH/$TOWN-$NATION/apxtri/.env
ExecStart=/bin/bash -lc "source $NODEPATH/$TOWN-$NATION/apxtri/.nvm/nvm.sh && npm run $MAINJS"
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable apxtri
sudo systemctl start apxtri
if [[ "$MODE" == "prod" ]]; then
echo "🔄 Redémarrage du service..."
sudo systemctl daemon-reload
sudo systemctl restart apxtri.service
fi
if [[ "$mode" == "dev" ]]; then
echo "🔧 Setting up development environment..."
sudo chown -R $APXTRI_USER:$APXTRI_USER "$NODEPATH" "$DATAPATH"
sudo chmod -R g+rwX "$NODEPATH" "$DATAPATH"
DEV_USER="${SUDO_USER:-$USER}"
sudo usermod -aG $APXTRI_USER "$DEV_USER"
# Ensure Caddy is running
if ! sudo systemctl is-active --quiet caddy; then
echo "Starting Caddy service..."
sudo systemctl start caddy || true
fi
fi
# ---
# ==== FINAL MESSAGE ====
echo
echo "============================================"
echo "INSTALLATION COMPLETE"
echo "============================================"
if [[ "$mode" == "dev" ]]; then
SCRIPT_PATH="/usr/local/bin/apxdev"
cat <<EOF | sudo tee $SCRIPT_PATH > /dev/null
#!/bin/bash
# This script runs the apxtri development server.
# It switches to the 'apxtri' user to ensure correct permissions and environment.
# The 'HOME' environment variable is set to the apxtri user's directory to ensure
# that nvm (Node Version Manager) can find its configuration files.
# The script then navigates to the project directory, sources the nvm script to
# activate it, uses the correct Node.js version, and finally starts the server
# in development mode using 'npm run dev'.
# All command-line arguments passed to 'apxdev' ('\$*') are forwarded to 'npm run dev'.
sudo -u apxtri env HOME="/opt/apxtowns/$TOWN-$NATION/apxtri" bash -c 'cd "/opt/apxtowns/$TOWN-$NATION/apxtri" && source .nvm/nvm.sh && nvm use default && npm run dev \$*'
EOF
sudo chmod +x $SCRIPT_PATH
echo "[DEV MODE INSTRUCTIONS]"
echo "Follow this guide to start developping on apxtri :"
echo "STEP 1: tap in your terminal 'code /opt/apxtowns', this will open you a new window in VS Code."
echo "STEP 2: click on 'file' on the top left corner of you VS Code Window, then click on 'Add Folder to Workspace', then go to /var/lib/ and click on 'apxtowns' then add it."
echo "STEP 3: To start the development server, run this single command from a new terminal in VS Code from anywhere:"
echo
echo " Run apxdev or sudo -u apxtri env HOME=\"/opt/apxtowns/${TOWN}-${NATION}/apxtri\" bash -c 'cd \"/opt/apxtowns/${TOWN}-${NATION}/apxtri\" && source .nvm/nvm.sh && npm run dev'"
echo
echo "To access logs, run:"
echo " tail -f /var/lib/apxtowns/data/apxtri/logs/*.log"
else
echo "[PROD MODE INSTRUCTIONS]"
echo "Start: sudo systemctl start apxtri"
echo "Stop: sudo systemctl stop apxtri"
echo "Restart: sudo systemctl restart apxtri"
echo "Status: sudo systemctl status apxtri"
echo "Logs: sudo journalctl -f -u apxtri.service"
fi
echo "✅ Mise à jour terminée avec succès."