@@ -17,7 +17,7 @@ set -euo pipefail
1717# --- Global Variables ---
1818# Determine the absolute path to Apollo root directory.
1919# Assumes this script is located at <APOLLO_ROOT_DIR>/docker/setup_host/config_system.sh
20- APOLLO_ROOT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) /../.." && pwd ) "
20+ APOLLO_ROOT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) /../.." && pwd) "
2121# use relative path for multiple instances
2222CORE_DUMP_DIR=" data/core"
2323CORE_DUMP_CONF_FILE=" /etc/sysctl.d/99-core-dump.conf"
@@ -26,6 +26,13 @@ UVCVIDEO_CONF_FILE="/etc/modprobe.d/uvcvideo.conf"
2626UDEV_RULES_SRC_DIR=" ${APOLLO_ROOT_DIR} /docker/setup_host/etc/udev/rules.d"
2727UDEV_RULES_DEST_DIR=" /etc/udev/rules.d"
2828
29+ # Source path of the service file within the project
30+ AUTOSERVICE_SRC_FILE=" ${APOLLO_ROOT_DIR} /docker/setup_host/etc/systemd/system/autostart.service"
31+ # Destination path for systemd services
32+ AUTOSERVICE_DEST_FILE=" /etc/systemd/system/autostart.service"
33+ # User who will run the autonomous driving stack. SUDO_USER is the user who invoked sudo.
34+ WHL_HOST_USER=" ${SUDO_USER:- $(whoami)} "
35+
2936# --- Color Definitions for Output ---
3037BOLD=' \033[1m'
3138RED=' \033[0;31m'
@@ -57,8 +64,8 @@ check_host_setup_pre_conditions() {
5764
5865 # 1. Check for root privileges
5966 if [ " $( id -u) " -ne 0 ]; then
60- error " This script must be run with root privileges (sudo)."
61- return 1
67+ error " This script must be run with root privileges (sudo)."
68+ return 1
6269 fi
6370
6471 # 2. Check if APOLLO_ROOT_DIR exists
@@ -87,6 +94,14 @@ check_host_setup_pre_conditions() {
8794 fi
8895 info " Udev rules source directory detected."
8996
97+ # 5. Check for existence of autostart service file
98+ if [ ! -f " ${AUTOSERVICE_SRC_FILE} " ]; then
99+ error " Autostart service file not found at '${AUTOSERVICE_SRC_FILE} '."
100+ error " Please ensure the service definition file is present."
101+ return 1
102+ fi
103+ info " Autostart service source file detected."
104+
90105 success " All host setup pre-conditions met."
91106 return 0
92107}
@@ -96,8 +111,8 @@ setup_core_dump() {
96111 info " Setting up core dump format..."
97112
98113 # Check if core dump configuration is already applied
99- if [ -f " ${CORE_DUMP_CONF_FILE} " ] && grep -q " kernel.core_pattern = ${CORE_DUMP_DIR} /core_%e.%p" " ${CORE_DUMP_CONF_FILE} " && \
100- [[ " $( sudo sysctl -n kernel.core_pattern) " == " ${CORE_DUMP_DIR} /core_%e.%p" ]]; then
114+ if [ -f " ${CORE_DUMP_CONF_FILE} " ] && grep -q " kernel.core_pattern = ${CORE_DUMP_DIR} /core_%e.%p" " ${CORE_DUMP_CONF_FILE} " &&
115+ [[ " $( sudo sysctl -n kernel.core_pattern) " == " ${CORE_DUMP_DIR} /core_%e.%p" ]]; then
101116 info " Core dump configuration already detected and active. Skipping."
102117 return 0
103118 fi
@@ -113,10 +128,13 @@ setup_core_dump() {
113128 fi
114129
115130 # Ensure the directory has appropriate permissions for core dumps
116- sudo chmod 0777 " ${CORE_DUMP_DIR} " || { error " Failed to set permissions for core dump directory: ${CORE_DUMP_DIR} ." ; return 1; }
131+ sudo chmod 0777 " ${CORE_DUMP_DIR} " || {
132+ error " Failed to set permissions for core dump directory: ${CORE_DUMP_DIR} ."
133+ return 1
134+ }
117135
118136 info " Writing core dump configuration to ${CORE_DUMP_CONF_FILE} ..."
119- sudo tee " ${CORE_DUMP_CONF_FILE} " > /dev/null << EOF
137+ sudo tee " ${CORE_DUMP_CONF_FILE} " > /dev/null << EOF
120138kernel.core_pattern = ${CORE_DUMP_DIR} /core_%e.%p
121139EOF
122140 if [ $? -ne 0 ]; then
@@ -152,7 +170,10 @@ setup_bazel_cache_dir() {
152170 fi
153171
154172 # Ensure permissions are appropriate for a shared cache
155- sudo chmod a+rwx " ${BAZEL_CACHE_DIR} " || { error " Failed to set permissions for Bazel cache directory." ; return 1; }
173+ sudo chmod a+rwx " ${BAZEL_CACHE_DIR} " || {
174+ error " Failed to set permissions for Bazel cache directory."
175+ return 1
176+ }
156177
157178 success " Bazel cache directory configured."
158179 return 0
@@ -263,7 +284,7 @@ configure_uvcvideo_module() {
263284 if [ -f " ${UVCVIDEO_CONF_FILE} " ] && grep -q " options uvcvideo clock=realtime" " ${UVCVIDEO_CONF_FILE} " ; then
264285 info " uvcvideo clock configuration already detected. Skipping write."
265286 else
266- sudo tee " ${UVCVIDEO_CONF_FILE} " > /dev/null << EOF
287+ sudo tee " ${UVCVIDEO_CONF_FILE} " > /dev/null << EOF
267288options uvcvideo clock=realtime
268289EOF
269290 if [ $? -ne 0 ]; then
@@ -323,6 +344,82 @@ add_user_to_docker_group() {
323344 success " User '${user} ' added to the Docker group. Please log out and back in for changes to take effect."
324345}
325346
347+ # Installs and enables the autostart systemd service.
348+ install_autostart_service () {
349+ info " Installing and configuring the autostart systemd service..."
350+
351+ # 1: Hard Fail on Root Installation (Security Best Practice) ---
352+ # Running the main AD stack as root is a major security risk.
353+ # We now block this by default and require an explicit, intentional override.
354+ if [[ " ${WHL_HOST_USER} " == " root" ]]; then
355+ error " Running the autonomous driving stack as 'root' is not allowed for security reasons."
356+ error " To override this critical check, set the environment variable ALLOW_ROOT_INSTALL=yes and re-run."
357+ if [[ " ${ALLOW_ROOT_INSTALL:- no} " != " yes" ]]; then
358+ return 1 # Hard fail, aborting the installation.
359+ else
360+ info " ALLOW_ROOT_INSTALL=yes detected. Proceeding with installation as root. THIS IS NOT RECOMMENDED."
361+ fi
362+ fi
363+
364+ # 2: Input Validation for Username (Prevent Command Injection) ---
365+ # Ensure the username consists only of safe, alphanumeric characters.
366+ if ! [[ " ${WHL_HOST_USER} " =~ ^[a-zA-Z0-9_][a-zA-Z0-9_-]* $ ]]; then
367+ error " Invalid username detected: '${WHL_HOST_USER} '. Usernames must be alphanumeric (with _ or -)."
368+ error " Aborting installation to prevent potential command injection."
369+ return 1
370+ fi
371+ info " Target user '${WHL_HOST_USER} ' validated."
372+
373+ # 3: Input Validation for Path (Prevent Command Injection) ---
374+ # Ensure the path is a valid absolute path and does not contain characters
375+ # that could break the sed command or be interpreted by the shell.
376+ if ! [[ " ${APOLLO_ROOT_DIR} " =~ ^/[a-zA-Z0-9_/.-]+$ ]]; then
377+ error " Invalid APOLLO_ROOT_DIR detected: '${APOLLO_ROOT_DIR} '."
378+ error " Path must be absolute and contain only safe characters (alphanumeric, /, _, ., -)."
379+ error " Aborting installation to prevent potential command injection."
380+ return 1
381+ fi
382+ info " Apollo root directory '${APOLLO_ROOT_DIR} ' validated."
383+
384+ info " Copying '${AUTOSERVICE_SRC_FILE} ' to '${AUTOSERVICE_DEST_FILE} '..."
385+ if ! cp " ${AUTOSERVICE_SRC_FILE} " " ${AUTOSERVICE_DEST_FILE} " ; then
386+ error " Failed to copy service file. Check permissions."
387+ return 1
388+ fi
389+
390+ # 4: Safer Replacement Method ---
391+ # By using a different delimiter for sed (like '#'), we make the replacement
392+ # robust even if the path contains the default '/' delimiter.
393+ # The validation above already mitigates this, but this is a defense-in-depth measure.
394+ info " Customizing service file with user='${WHL_HOST_USER} ' and path='${APOLLO_ROOT_DIR} '..."
395+ if ! sed -i " s#__USER__#${WHL_HOST_USER} #g" " ${AUTOSERVICE_DEST_FILE} " ; then
396+ error " Failed to replace user placeholder in service file."
397+ return 1
398+ fi
399+ if ! sed -i " s#__APOLLO_ROOT_DIR__#${APOLLO_ROOT_DIR} #g" " ${AUTOSERVICE_DEST_FILE} " ; then
400+ error " Failed to replace path placeholder in service file."
401+ return 1
402+ fi
403+
404+ # Reload the systemd daemon
405+ info " Reloading systemd daemon..."
406+ if ! systemctl daemon-reload; then
407+ error " Failed to reload systemd daemon. Run 'journalctl -xe' for details."
408+ return 1
409+ fi
410+
411+ # Enable the service
412+ info " Enabling 'autostart.service' to run on boot..."
413+ if ! systemctl enable autostart.service; then
414+ error " Failed to enable autostart.service."
415+ return 1
416+ fi
417+
418+ success " Autostart service installed and enabled successfully."
419+ info " The autonomous driving system will now start automatically on the next boot."
420+ return 0
421+ }
422+
326423# --- Main Host Setup Orchestration Function ---
327424# This is the primary entry point for setting up the host machine.
328425setup_host_machine () {
@@ -370,6 +467,12 @@ setup_host_machine() {
370467 return 1
371468 fi
372469
470+ # 8. Install and enable the autostart service
471+ if ! install_autostart_service; then
472+ error " Failed to install the autostart service. Host setup is incomplete."
473+ return 1
474+ fi
475+
373476 success " Host machine setup completed successfully!"
374477 return 0 # Final success
375478}
@@ -382,7 +485,7 @@ main() {
382485 # Any other argument will result in an error message.
383486 if [ " $# " -eq 0 ] || [ " $1 " == " install" ]; then
384487 if [ " $# " -eq 0 ]; then
385- info " No argument provided. Defaulting to 'install' mode."
488+ info " No argument provided. Defaulting to 'install' mode."
386489 fi
387490 setup_host_machine
388491 else
0 commit comments