@@ -91,6 +91,12 @@ step_header() {
9191 echo
9292}
9393
94+ # ── YAML helpers ─────────────────────────────────────────────────────────────
95+
96+ yaml_quote () {
97+ printf " '%s'" " $( printf ' %s' " $1 " | sed " s/'/''/g" ) "
98+ }
99+
94100# ── Input helpers ───────────────────────────────────────────────────────────
95101
96102ask () {
@@ -556,91 +562,144 @@ ask "Folder name" "$INSTALL_DIR"
556562INSTALL_DIR=" $REPLY "
557563
558564# ═══════════════════════════════════════════════════════════════════════════
559- # STEP — ADMIN PASSWORD
565+ # DETECT EXISTING INSTALLATION
560566# ═══════════════════════════════════════════════════════════════════════════
561567
562- ADMIN_PASSWORD=" "
568+ SKIP_DATA=false
569+ SKIP_CONFIG=false
563570
564- (( local_step++ ))
565- cls
566- step_header " $local_step " " Protect the Admin Panel"
571+ if [[ -d " ${INSTALL_DIR} /data" ]] || [[ -f " ${INSTALL_DIR} /config.yaml" ]]; then
572+ cls
567573
568- box_top
569- box_empty
570- box_line " The Admin Panel lets you manage agents, backends,"
571- box_line " API keys, and everything else in Magec."
572- box_empty
573- box_sep
574- box_empty
575- box_line " Setting a password will protect the Admin API"
576- box_line " and the web panel — no one can access them"
577- box_line " without logging in first."
578- box_empty
579- box_line " ${DIM} Without a password, anyone on the network can${NC} "
580- box_line " ${DIM} change your configuration.${NC} "
581- box_empty
582- box_sep
583- box_empty
584- box_line " ${DIM} Leave blank to skip (not recommended for servers).${NC} "
585- box_line " ${DIM} You can set it later in config.yaml or via:${NC} "
586- box_line " ${CYAN} MAGEC_ADMIN_PASSWORD${NC} "
587- box_empty
588- box_bottom
589- echo
574+ (( local_step++ ))
575+ step_header " $local_step " " Existing installation detected"
590576
591- printf " ${CYAN} ▸${NC} Admin password (input hidden): "
592- read -rs REPLY < /dev/tty
593- echo
594- ADMIN_PASSWORD=" $REPLY "
577+ box_top
578+ box_empty
579+ box_line " ${YELLOW} Existing Magec data found${NC} " " " " center"
580+ box_empty
581+ box_sep
582+ box_empty
583+ if [[ -d " ${INSTALL_DIR} /data" ]]; then
584+ box_line " A ${BOLD} data/${NC} folder exists in ${CYAN}${INSTALL_DIR} /${NC} ."
585+ box_line " It contains your agents, backends, secrets,"
586+ box_line " conversations, and other configuration."
587+ box_empty
588+ fi
589+ if [[ -f " ${INSTALL_DIR} /config.yaml" ]]; then
590+ box_line " A ${BOLD} config.yaml${NC} exists with your admin password,"
591+ box_line " encryption key, and other settings."
592+ box_empty
593+ fi
594+ box_sep
595+ box_empty
596+ box_line " ${RED} Overwriting will permanently delete this data.${NC} "
597+ box_empty
598+ box_bottom
599+ echo
595600
596- if [[ -n " $ADMIN_PASSWORD " ]]; then
597- ok " Password set"
598- else
599- info " No password — Admin Panel will be open"
601+ choose \
602+ " Keep my data and config (recommended)" \
603+ " Overwrite everything (data will be lost)"
604+
605+ if [[ " $REPLY " == " 1" ]]; then
606+ SKIP_DATA=true
607+ SKIP_CONFIG=true
608+ ok " Your existing installation will be preserved"
609+ else
610+ warn " Existing data will be overwritten"
611+ fi
600612fi
601613
602614# ═══════════════════════════════════════════════════════════════════════════
603- # STEP — ENCRYPTION KEY
615+ # STEP — ADMIN PASSWORD
604616# ═══════════════════════════════════════════════════════════════════════════
605617
618+ ADMIN_PASSWORD=" "
606619ENCRYPTION_KEY=" "
607620
608- (( local_step++ ))
609- cls
610- step_header " $local_step " " Encrypt your secrets"
621+ if ! $SKIP_CONFIG ; then
611622
612- box_top
613- box_empty
614- box_line " Magec can store sensitive data like API keys"
615- box_line " for cloud providers (OpenAI, Anthropic, etc.)."
616- box_empty
617- box_sep
618- box_empty
619- box_line " An encryption key protects these secrets on disk."
620- box_line " Without it, they are stored as plain text in"
621- box_line " ${CYAN} data/store.json${NC} ."
622- box_empty
623- box_line " ${DIM} This key is independent from the admin password,${NC} "
624- box_line " ${DIM} so you can rotate one without affecting the other.${NC} "
625- box_empty
626- box_sep
627- box_empty
628- box_line " ${DIM} Leave blank to skip (secrets stored unencrypted).${NC} "
629- box_line " ${DIM} You can set it later in config.yaml or via:${NC} "
630- box_line " ${CYAN} MAGEC_ENCRYPTION_KEY${NC} "
631- box_empty
632- box_bottom
633- echo
623+ (( local_step++ ))
624+ cls
625+ step_header " $local_step " " Protect the Admin Panel"
634626
635- printf " ${CYAN} ▸${NC} Encryption key (input hidden): "
636- read -rs REPLY < /dev/tty
637- echo
638- ENCRYPTION_KEY=" $REPLY "
627+ box_top
628+ box_empty
629+ box_line " The Admin Panel lets you manage agents, backends,"
630+ box_line " API keys, and everything else in Magec."
631+ box_empty
632+ box_sep
633+ box_empty
634+ box_line " Setting a password will protect the Admin API"
635+ box_line " and the web panel — no one can access them"
636+ box_line " without logging in first."
637+ box_empty
638+ box_line " ${DIM} Without a password, anyone on the network can${NC} "
639+ box_line " ${DIM} change your configuration.${NC} "
640+ box_empty
641+ box_sep
642+ box_empty
643+ box_line " ${DIM} Leave blank to skip (not recommended for servers).${NC} "
644+ box_line " ${DIM} You can set it later in config.yaml or via:${NC} "
645+ box_line " ${CYAN} MAGEC_ADMIN_PASSWORD${NC} "
646+ box_empty
647+ box_bottom
648+ echo
649+
650+ printf " ${CYAN} ▸${NC} Admin password (input hidden): "
651+ read -rs REPLY < /dev/tty
652+ echo
653+ ADMIN_PASSWORD=" $REPLY "
654+
655+ if [[ -n " $ADMIN_PASSWORD " ]]; then
656+ ok " Password set"
657+ else
658+ info " No password — Admin Panel will be open"
659+ fi
660+
661+ # ═══════════════════════════════════════════════════════════════════════════
662+ # STEP — ENCRYPTION KEY
663+ # ═══════════════════════════════════════════════════════════════════════════
664+
665+ (( local_step++ ))
666+ cls
667+ step_header " $local_step " " Encrypt your secrets"
668+
669+ box_top
670+ box_empty
671+ box_line " Magec can store sensitive data like API keys"
672+ box_line " for cloud providers (OpenAI, Anthropic, etc.)."
673+ box_empty
674+ box_sep
675+ box_empty
676+ box_line " An encryption key protects these secrets on disk."
677+ box_line " Without it, they are stored as plain text in"
678+ box_line " ${CYAN} data/store.json${NC} ."
679+ box_empty
680+ box_line " ${DIM} This key is independent from the admin password,${NC} "
681+ box_line " ${DIM} so you can rotate one without affecting the other.${NC} "
682+ box_empty
683+ box_sep
684+ box_empty
685+ box_line " ${DIM} Leave blank to skip (secrets stored unencrypted).${NC} "
686+ box_line " ${DIM} You can set it later in config.yaml or via:${NC} "
687+ box_line " ${CYAN} MAGEC_ENCRYPTION_KEY${NC} "
688+ box_empty
689+ box_bottom
690+ echo
691+
692+ printf " ${CYAN} ▸${NC} Encryption key (input hidden): "
693+ read -rs REPLY < /dev/tty
694+ echo
695+ ENCRYPTION_KEY=" $REPLY "
696+
697+ if [[ -n " $ENCRYPTION_KEY " ]]; then
698+ ok " Encryption key set"
699+ else
700+ info " No encryption — secrets will be stored in plain text"
701+ fi
639702
640- if [[ -n " $ENCRYPTION_KEY " ]]; then
641- ok " Encryption key set"
642- else
643- info " No encryption — secrets will be stored in plain text"
644703fi
645704
646705# ═══════════════════════════════════════════════════════════════════════════
@@ -678,12 +737,20 @@ if [[ "$INSTALL_METHOD" == "2" ]] && $GPU; then
678737 box_line " ${BOLD} GPU:${NC} NVIDIA"
679738fi
680739box_line " ${BOLD} Folder:${NC} $INSTALL_DIR /"
681- pass_label=" ${GREEN} Set${NC} "
682- [[ -z " $ADMIN_PASSWORD " ]] && pass_label=" ${YELLOW} None (open)${NC} "
683- box_line " ${BOLD} Admin password:${NC} $pass_label "
684- enc_label=" ${GREEN} Set${NC} "
685- [[ -z " $ENCRYPTION_KEY " ]] && enc_label=" ${YELLOW} None (plain text)${NC} "
686- box_line " ${BOLD} Encryption key:${NC} $enc_label "
740+ if $SKIP_CONFIG ; then
741+ box_line " ${BOLD} Admin password:${NC} ${GREEN} Kept existing${NC} "
742+ box_line " ${BOLD} Encryption key:${NC} ${GREEN} Kept existing${NC} "
743+ else
744+ pass_label=" ${GREEN} Set${NC} "
745+ [[ -z " $ADMIN_PASSWORD " ]] && pass_label=" ${YELLOW} None (open)${NC} "
746+ box_line " ${BOLD} Admin password:${NC} $pass_label "
747+ enc_label=" ${GREEN} Set${NC} "
748+ [[ -z " $ENCRYPTION_KEY " ]] && enc_label=" ${YELLOW} None (plain text)${NC} "
749+ box_line " ${BOLD} Encryption key:${NC} $enc_label "
750+ fi
751+ if $SKIP_DATA ; then
752+ box_line " ${BOLD} Data:${NC} ${GREEN} Kept existing${NC} "
753+ fi
687754box_empty
688755box_bottom
689756echo
@@ -1251,8 +1318,16 @@ install_binary() {
12511318
12521319 echo
12531320 info " Creating configuration files..."
1254- generate_config_yaml
1255- generate_store_json
1321+ if ! $SKIP_CONFIG ; then
1322+ generate_config_yaml
1323+ else
1324+ ok " config.yaml (kept existing)"
1325+ fi
1326+ if ! $SKIP_DATA ; then
1327+ generate_store_json
1328+ else
1329+ ok " data/store.json (kept existing)"
1330+ fi
12561331
12571332 print_success
12581333}
@@ -1383,8 +1458,16 @@ install_containers() {
13831458
13841459 info " Creating configuration files..."
13851460 generate_docker_compose
1386- generate_config_yaml
1387- generate_store_json
1461+ if ! $SKIP_CONFIG ; then
1462+ generate_config_yaml
1463+ else
1464+ ok " config.yaml (kept existing)"
1465+ fi
1466+ if ! $SKIP_DATA ; then
1467+ generate_store_json
1468+ else
1469+ ok " data/store.json (kept existing)"
1470+ fi
13881471
13891472 ok " All files created"
13901473
@@ -1411,11 +1494,11 @@ generate_config_yaml() {
14111494 onnx_line=" onnxLibraryPath: ${ONNX_LIB_PATH} "
14121495 fi
14131496
1414- local admin_pass_value=' ${MAGEC_ADMIN_PASSWORD}'
1415- [[ -n " $ADMIN_PASSWORD " ]] && admin_pass_value=" $ADMIN_PASSWORD "
1497+ local admin_pass_value=" $( yaml_quote ' ${MAGEC_ADMIN_PASSWORD}' ) "
1498+ [[ -n " $ADMIN_PASSWORD " ]] && admin_pass_value=" $( yaml_quote " $ ADMIN_PASSWORD" ) "
14161499
1417- local enc_key_value=' ${MAGEC_ENCRYPTION_KEY}'
1418- [[ -n " $ENCRYPTION_KEY " ]] && enc_key_value=" $ENCRYPTION_KEY "
1500+ local enc_key_value=" $( yaml_quote ' ${MAGEC_ENCRYPTION_KEY}' ) "
1501+ [[ -n " $ENCRYPTION_KEY " ]] && enc_key_value=" $( yaml_quote " $ ENCRYPTION_KEY" ) "
14191502
14201503 cat > config.yaml << YAML
14211504server:
@@ -1753,7 +1836,13 @@ EOF
17531836 box_empty
17541837 fi
17551838
1756- if [[ -n " $ADMIN_PASSWORD " ]]; then
1839+ if $SKIP_CONFIG ; then
1840+ box_sep
1841+ box_empty
1842+ box_line " ${GREEN} Config preserved${NC} — your admin password and"
1843+ box_line " encryption key are unchanged in config.yaml."
1844+ box_empty
1845+ elif [[ -n " $ADMIN_PASSWORD " ]]; then
17571846 box_sep
17581847 box_empty
17591848 box_line " ${BOLD} Admin password:${NC} ${CYAN}${ADMIN_PASSWORD}${NC} "
@@ -1770,21 +1859,23 @@ EOF
17701859 box_empty
17711860 fi
17721861
1773- if [[ -n " $ENCRYPTION_KEY " ]]; then
1774- box_sep
1775- box_empty
1776- box_line " ${BOLD} Encryption key:${NC} ${CYAN}${ENCRYPTION_KEY}${NC} "
1777- box_empty
1778- box_line " ${DIM} Used to encrypt API keys and secrets on disk.${NC} "
1779- box_line " ${DIM} Saved in config.yaml → server.encryptionKey${NC} "
1780- box_empty
1781- else
1782- box_sep
1783- box_empty
1784- box_line " ${YELLOW} No encryption key set.${NC} Secrets stored in plain text."
1785- box_line " ${DIM} Set one later in config.yaml or via env var:${NC} "
1786- box_line " ${CYAN} MAGEC_ENCRYPTION_KEY=yourkey${NC} "
1787- box_empty
1862+ if ! $SKIP_CONFIG ; then
1863+ if [[ -n " $ENCRYPTION_KEY " ]]; then
1864+ box_sep
1865+ box_empty
1866+ box_line " ${BOLD} Encryption key:${NC} ${CYAN}${ENCRYPTION_KEY}${NC} "
1867+ box_empty
1868+ box_line " ${DIM} Used to encrypt API keys and secrets on disk.${NC} "
1869+ box_line " ${DIM} Saved in config.yaml → server.encryptionKey${NC} "
1870+ box_empty
1871+ else
1872+ box_sep
1873+ box_empty
1874+ box_line " ${YELLOW} No encryption key set.${NC} Secrets stored in plain text."
1875+ box_line " ${DIM} Set one later in config.yaml or via env var:${NC} "
1876+ box_line " ${CYAN} MAGEC_ENCRYPTION_KEY=yourkey${NC} "
1877+ box_empty
1878+ fi
17881879 fi
17891880
17901881 if [[ " $INSTALL_METHOD " == " 1" ]]; then
0 commit comments