diff --git a/script/install/install_production.sh b/script/install/install_production.sh index 5895003..e113acb 100755 --- a/script/install/install_production.sh +++ b/script/install/install_production.sh @@ -8,7 +8,7 @@ sudo adduser --system --quiet --shell=/bin/bash --home=/${EL_USER} --gecos 'ERPL sudo adduser ${EL_USER} sudo echo -e "\n---- Creating the ERPLIBRE PostgreSQL User ----" -sudo su - postgres -c "createuser -s ${EL_USER}" 2> /dev/null || true +sudo su - postgres -c "createuser -s ${EL_USER}" 2>/dev/null || true #echo -e "\n---- Create Log directory ----" #sudo mkdir /var/log/${EL_USER} @@ -22,8 +22,8 @@ sudo chown -R ${EL_USER}:${EL_USER} ${EL_HOME} # Install ERPLIBRE #-------------------------------------------------- echo -e "\n==== Clone this installation ====" -REMOTE_URL_GIT=`git remote get-url origin` -BRANCH_GIT=`git rev-parse --abbrev-ref HEAD` +REMOTE_URL_GIT=$(git remote get-url origin) +BRANCH_GIT=$(git rev-parse --abbrev-ref HEAD) if [ "HEAD" = "${BRANCH_GIT}" ]; then # Checkout version of env_var.sh sudo su ${EL_USER} -c "git clone --branch v${ERPLIBRE_VERSION} ${REMOTE_URL_GIT} ${EL_HOME_ERPLIBRE}" @@ -43,9 +43,9 @@ cd ${LAST_PWD} #-------------------------------------------------- # Adding ERPLIBRE as a daemon #-------------------------------------------------- -./script/install/install_daemon.sh +./script/systemd/install_daemon.sh #-------------------------------------------------- # Install Nginx if needed #-------------------------------------------------- -./script/install/install_production_nginx.sh \ No newline at end of file +./script/install/install_production_nginx.sh diff --git a/script/systemd/install_daemon.py b/script/systemd/install_daemon.py new file mode 100755 index 0000000..bfd6008 --- /dev/null +++ b/script/systemd/install_daemon.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +# © 2021-2024 TechnoLibre (http://www.technolibre.ca) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +import argparse +import os +import stat +import subprocess +import sys +from pathlib import Path + +UNIT_TEMPLATE = """[Unit] +Description=ERPLibre for {user} +Requires=postgresql.service +After=network.target network-online.target postgresql.service + +[Service] +Type=simple +SyslogIdentifier={user} +PermissionsStartOnly=true +User={user} +Group={user} +Restart=always +RestartSec=5 +PIDFile={home_erplibre}/.venv.erplibre/service.pid +ExecStart={home_erplibre}/run.sh{EXEC_PARAM} +WorkingDirectory={home_erplibre} +StandardOutput=journal+console + +[Install] +WantedBy=multi-user.target +""" + + +def ensure_root(): + if os.geteuid() != 0: + sys.exit("❌ This script must be run as root (use sudo or root).") + + +def run(cmd: list[str]) -> None: + subprocess.run(cmd, check=True) + + +def w_cmd(param: str, arg: str = None) -> str: + if not arg: + if type(arg) is str: + return "" + return param + return f"{param} {arg}" + + +def main(): + parser = argparse.ArgumentParser( + description="Create and enable a SystemD service for ERPLibre (Python equivalent of the bash script)." + ) + + # Exposed variables as configurable parameters + parser.add_argument( + "--user", + required=True, + help="Linux user running the service (e.g. erplibre)", + ) + parser.add_argument( + "--home-erplibre", + help="Path to erplibre directory, workspace root path.", + ) + parser.add_argument("--port", help="Application port (for information).") + parser.add_argument( + "--database", + help="Database name to run only with it (for information).", + ) + parser.add_argument( + "--config-name", + help="Service name (and systemd file name without .service). Default: user", + ) + + # Utility flags + parser.add_argument( + "--no-enable", + action="store_true", + help="Do not enable service on boot.", + ) + parser.add_argument( + "--no-restart", + action="store_true", + help="Do not restart the service after setup.", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Show what would be done without changing the system.", + ) + args = parser.parse_args() + + ensure_root() + + # Default paths and fallback values (same logic as in the bash script) + el_user = args.user + el_home_erplibre = args.home_erplibre or os.getcwd() + el_config_name = args.config_name or f"erplibre_{el_user}_{os.path.basename(os.getcwd())}" + exec_param = ( + " " + + f" {w_cmd("-d", args.database or "")} {w_cmd("-p", args.port or "")}".strip() + ) + + # Render the systemd service file content + unit_content = UNIT_TEMPLATE.format( + user=el_user, + home_erplibre=el_home_erplibre, + EXEC_PARAM=exec_param, + ) + + unit_dest_path = Path(f"/etc/systemd/system/{el_config_name}.service") + + print("* Final systemd file location:", unit_dest_path) + + if args.dry_run: + print("\n--- GENERATED CONTENT ---\n") + print(unit_content) + print("\n--- END ---") + print("\n(dry-run) No files written, no systemctl commands executed.") + return + + # Write temporary unit file + unit_dest_path.write_text(unit_content, encoding="utf-8") + + # chmod 755 + print("* Setting permissions to 755") + unit_dest_path.chmod( + stat.S_IRUSR + | stat.S_IWUSR + | stat.S_IXUSR + | stat.S_IRGRP + | stat.S_IXGRP + | stat.S_IROTH + | stat.S_IXOTH + ) + + # chown root:root + print("* Changing owner to root:root") + os.chown(unit_dest_path, 0, 0) + + # Sanity checks + if not Path(el_home_erplibre).exists(): + print(f"⚠️ Warning: {el_home_erplibre} does not exist.") + if not Path(el_home_erplibre, "run.sh").exists(): + print(f"⚠️ Warning: {el_home_erplibre}/run.sh does not exist.") + + # Reload systemd and enable service + print("* Reloading systemd daemon") + run(["systemctl", "daemon-reload"]) + + if not args.no_enable: + print(f"* Enabling service at boot: {el_config_name}.service") + run(["systemctl", "enable", f"{el_config_name}.service"]) + else: + print("* (skip) enable step") + + if not args.no_restart: + print(f"* Restarting service: {el_config_name}.service") + run(["systemctl", "restart", f"{el_config_name}.service"]) + else: + print("* (skip) restart step") + + # Summary (equivalent of bash echo block) + print("\n-----------------------------------------------------------") + print("Done! ERPLibre service created and started. Details:") + print(f"Port: {args.port}") + print(f"Service user: {el_user}") + print(f"Systemd file: {unit_dest_path}") + print(f"Start: systemctl start {el_config_name}") + print(f"Stop: systemctl stop {el_config_name}") + print(f"Restart: systemctl restart {el_config_name}") + print(f"Status: systemctl status {el_config_name}") + print(f"Logs: journalctl -feu {el_config_name}") + print("-----------------------------------------------------------") + + +if __name__ == "__main__": + main() diff --git a/script/install/install_daemon.sh b/script/systemd/install_daemon.sh similarity index 98% rename from script/install/install_daemon.sh rename to script/systemd/install_daemon.sh index c1330ed..cfc2bd2 100755 --- a/script/install/install_daemon.sh +++ b/script/systemd/install_daemon.sh @@ -16,7 +16,7 @@ #-------------------------------------------------- echo -e "\n* Create init file" sudo rm -f /tmp/${EL_CONFIG} -cat < /tmp/${EL_CONFIG} +cat </tmp/${EL_CONFIG} [Unit] Description=${EL_USER} Requires=postgresql.service