openship 0.4.5 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -24
- package/dist/bare-2HYDXQEH.js +23 -0
- package/dist/{bowser-L6PVH37V.js → bowser-O3AEA6AN.js} +3 -1
- package/dist/{chunk-YFLQGDN2.js → chunk-4TJC4JZQ.js} +18 -9
- package/dist/{chunk-JXQCFTDV.js → chunk-4Z5QO7N6.js} +4 -2
- package/dist/{chunk-JJVSOE4I.js → chunk-5MZ624VX.js} +2 -0
- package/dist/{chunk-TDFK6ISF.js → chunk-6APIPIJY.js} +6 -4
- package/dist/{chunk-3LCRNQ2C.js → chunk-6APULWSU.js} +151 -133
- package/dist/{chunk-FTBXJ2VA.js → chunk-6B5YCFFV.js} +6 -4
- package/dist/{chunk-MDFYN2QH.js → chunk-AVIB7CT7.js} +3 -1
- package/dist/{chunk-W7KGHYLV.js → chunk-DYPH4HCI.js} +2 -0
- package/dist/{chunk-5WI7ZXOC.js → chunk-EI575GHN.js} +4 -2
- package/dist/{chunk-Z6EKX6CX.js → chunk-FPRHYBY2.js} +2 -0
- package/dist/{chunk-FZJX6XP7.js → chunk-FRNAR33O.js} +4 -2
- package/dist/{chunk-XRWV5ZNR.js → chunk-FXTBHTWY.js} +360 -42
- package/dist/chunk-ILFETZOM.js +131 -0
- package/dist/{chunk-E3ZPCNPU.js → chunk-IMBD5PZ5.js} +251 -105
- package/dist/{chunk-VJTXRCTT.js → chunk-IPYPMI3S.js} +10 -6
- package/dist/{chunk-PARRPUXN.js → chunk-IXCHURVK.js} +5 -3
- package/dist/{chunk-YJAS5RQX.js → chunk-JYGD5WSN.js} +2 -0
- package/dist/{chunk-JWBXYO24.js → chunk-KI2EY3WB.js} +2 -0
- package/dist/{chunk-YVXF6GGR.js → chunk-L2VOGB2X.js} +5 -104
- package/dist/{chunk-K5OH5U7N.js → chunk-MZ2WEHHY.js} +5 -3
- package/dist/{chunk-SJBR527P.js → chunk-O6ZZF52V.js} +3 -1
- package/dist/{chunk-VLPJLXXB.js → chunk-OWED2GRM.js} +3 -1
- package/dist/{chunk-C4FOQJ63.js → chunk-OXWDY22G.js} +4 -2
- package/dist/{chunk-NPVJYR7M.js → chunk-Q2CIRAOK.js} +2 -0
- package/dist/chunk-R5BHFFAV.js +282 -0
- package/dist/{chunk-JYAGTMSJ.js → chunk-RPHRPFEH.js} +2 -0
- package/dist/{chunk-R74UB4X4.js → chunk-SJIFLLX4.js} +397 -85
- package/dist/{chunk-HYL4QYZM.js → chunk-TGIINPVM.js} +13 -2
- package/dist/{chunk-SYCZE6FQ.js → chunk-TYVME3XD.js} +7 -1
- package/dist/{chunk-UMYQALBH.js → chunk-UXWAVM4C.js} +1788 -1484
- package/dist/{chunk-HDV4NSA3.js → chunk-V6AN6XLZ.js} +16 -6
- package/dist/{chunk-3YCMJRDZ.js → chunk-VDMQJHPI.js} +36 -15
- package/dist/{chunk-RZPDJC2J.js → chunk-VFINNTUL.js} +20 -1
- package/dist/{chunk-65KKUJBR.js → chunk-VWPEKOH6.js} +4 -2
- package/dist/{chunk-GHXGCANU.js → chunk-W73X43R7.js} +4 -2
- package/dist/{chunk-7EYFCKZX.js → chunk-XFCDYZUQ.js} +8 -6
- package/dist/cloud-2KXREXMO.js +30 -0
- package/dist/{cloud-7IGG45CF.js → cloud-7QYOGF7F.js} +4 -2
- package/dist/detect-2XSCFFTF.js +44 -0
- package/dist/{dist-NQB6QGX3.js → dist-IQJ6H6UZ.js} +4 -2
- package/dist/{dist-es-DCR6UJMP.js → dist-es-5DY7K32L.js} +7 -5
- package/dist/{dist-es-TYYZ5KEF.js → dist-es-JSTDUS7Q.js} +7 -5
- package/dist/{dist-es-7EZIM4JU.js → dist-es-OSNJBLXB.js} +6 -4
- package/dist/{dist-es-6RSPR56Q.js → dist-es-RYHIPOTN.js} +15 -13
- package/dist/{dist-es-33Z3Y6VE.js → dist-es-VNKHQVIB.js} +5 -3
- package/dist/{dist-es-D6QQVWRZ.js → dist-es-WV4AMOII.js} +9 -7
- package/dist/{dist-es-GMEQINIE.js → dist-es-X3B5QYKB.js} +7 -5
- package/dist/docker-LODK5Y2S.js +16 -0
- package/dist/docker-edge-executor-VHW3JPJS.js +13 -0
- package/dist/edge-import-ZQ4Y5HEA.js +45 -0
- package/dist/ensure-container-edge-ED25XL3Z.js +31 -0
- package/dist/{event-streams-G7F6Q7QY.js → event-streams-EHRAKL75.js} +5 -3
- package/dist/{executor-O5NR7LMP.js → executor-YPT6RH6O.js} +9 -7
- package/dist/index.d.ts +2 -1
- package/dist/index.js +279 -245
- package/dist/{loadSso-LH753OSJ.js → loadSso-46FQRIZS.js} +11 -9
- package/dist/local-executor-V7U5VOZW.js +12 -0
- package/dist/nginx-XWJAOGS4.js +24 -0
- package/dist/{noop-6KC6HRDB.js → noop-FMMFG2EZ.js} +4 -2
- package/dist/{openresty-lua-KFCOJAG4.js → openresty-lua-4WLGDSER.js} +11 -3
- package/dist/server/engine/ChangeLog +2289 -0
- package/dist/server/engine/Documentations +5 -0
- package/dist/server/engine/LICENSE +674 -0
- package/dist/server/engine/README.md +34 -0
- package/dist/server/engine/conf/amavisd +150 -0
- package/dist/server/engine/conf/clamav +71 -0
- package/dist/server/engine/conf/core +632 -0
- package/dist/server/engine/conf/dovecot +151 -0
- package/dist/server/engine/conf/fail2ban +72 -0
- package/dist/server/engine/conf/global +698 -0
- package/dist/server/engine/conf/iredapd +52 -0
- package/dist/server/engine/conf/logwatch +28 -0
- package/dist/server/engine/conf/postfix +97 -0
- package/dist/server/engine/conf/postgresql +93 -0
- package/dist/server/engine/conf/spamassassin +39 -0
- package/dist/server/engine/dialog/config_via_dialog.sh +258 -0
- package/dist/server/engine/dialog/optional_components.sh +122 -0
- package/dist/server/engine/dialog/pgsql_config.sh +52 -0
- package/dist/server/engine/dialog/virtual_domain_config.sh +94 -0
- package/dist/server/engine/functions/amavisd.sh +267 -0
- package/dist/server/engine/functions/backend.sh +85 -0
- package/dist/server/engine/functions/clamav.sh +100 -0
- package/dist/server/engine/functions/cleanup.sh +393 -0
- package/dist/server/engine/functions/dovecot.sh +583 -0
- package/dist/server/engine/functions/fail2ban.sh +209 -0
- package/dist/server/engine/functions/iredapd.sh +356 -0
- package/dist/server/engine/functions/optional_components.sh +24 -0
- package/dist/server/engine/functions/packages.sh +522 -0
- package/dist/server/engine/functions/packages_freebsd.sh +179 -0
- package/dist/server/engine/functions/postfix.sh +457 -0
- package/dist/server/engine/functions/postgresql.sh +239 -0
- package/dist/server/engine/functions/spamassassin.sh +49 -0
- package/dist/server/engine/functions/system_accounts.sh +128 -0
- package/dist/server/engine/iRedMail.sh +144 -0
- package/dist/server/engine/pkgs/get_all.sh +338 -0
- package/dist/server/engine/pkgs/pkgs.freebsd.sha256 +3 -0
- package/dist/server/engine/pkgs/pkgs.openbsd.sha256 +6 -0
- package/dist/server/engine/pkgs/pkgs.sha256 +1 -0
- package/dist/server/engine/samples/amavisd/amavisd.conf +677 -0
- package/dist/server/engine/samples/amavisd/amavisd.mysql +278 -0
- package/dist/server/engine/samples/amavisd/amavisd.pgsql +253 -0
- package/dist/server/engine/samples/amavisd/amavisd.schema +942 -0
- package/dist/server/engine/samples/amavisd/default_spam_policy.sql +46 -0
- package/dist/server/engine/samples/dovecot/dovecot-2.4-mariadb.conf +758 -0
- package/dist/server/engine/samples/dovecot/dovecot-2.4-openldap.conf +767 -0
- package/dist/server/engine/samples/dovecot/dovecot-2.4-pgsql.conf +762 -0
- package/dist/server/engine/samples/dovecot/dovecot-last-login.conf +50 -0
- package/dist/server/engine/samples/dovecot/dovecot-ldap.conf +21 -0
- package/dist/server/engine/samples/dovecot/dovecot-share-folder.conf +22 -0
- package/dist/server/engine/samples/dovecot/dovecot-sql.conf +28 -0
- package/dist/server/engine/samples/dovecot/dovecot-used-quota.conf +13 -0
- package/dist/server/engine/samples/dovecot/dovecot.conf +484 -0
- package/dist/server/engine/samples/dovecot/dovecot.sieve +7 -0
- package/dist/server/engine/samples/dovecot/dovecot2-quota-warning.sh +38 -0
- package/dist/server/engine/samples/dovecot/sql/imap_share_folder.mysql +16 -0
- package/dist/server/engine/samples/dovecot/sql/last_login.mysql +12 -0
- package/dist/server/engine/samples/dovecot/sql/used_quota.mysql +26 -0
- package/dist/server/engine/samples/dovecot/systemd/override.conf +3 -0
- package/dist/server/engine/samples/fail2ban/action.d/banned_db.conf +9 -0
- package/dist/server/engine/samples/fail2ban/bin/fail2ban_banned_db +268 -0
- package/dist/server/engine/samples/fail2ban/fail2ban.local +17 -0
- package/dist/server/engine/samples/fail2ban/filter.d/dovecot.iredmail.conf +5 -0
- package/dist/server/engine/samples/fail2ban/filter.d/postfix-pregreet.iredmail.conf +16 -0
- package/dist/server/engine/samples/fail2ban/filter.d/postfix.iredmail.conf +18 -0
- package/dist/server/engine/samples/fail2ban/filter.d/roundcube.iredmail.conf +9 -0
- package/dist/server/engine/samples/fail2ban/jail.d/dovecot.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/nginx-http-auth.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/postfix-pregreet.local +9 -0
- package/dist/server/engine/samples/fail2ban/jail.d/postfix.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/roundcube.local +9 -0
- package/dist/server/engine/samples/fail2ban/jail.d/sogo.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/sshd.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.local +6 -0
- package/dist/server/engine/samples/fail2ban/openbsd/rc +27 -0
- package/dist/server/engine/samples/fail2ban/sql/fail2ban.mysql +49 -0
- package/dist/server/engine/samples/fail2ban/sql/fail2ban.pgsql +48 -0
- package/dist/server/engine/samples/firewall/firewalld/services/ssh.xml +6 -0
- package/dist/server/engine/samples/firewall/firewalld/zones/iredmail.xml +15 -0
- package/dist/server/engine/samples/firewall/iptables/ip6tables.init.debian +362 -0
- package/dist/server/engine/samples/firewall/iptables/ip6tables.rules +53 -0
- package/dist/server/engine/samples/firewall/iptables/iptables.init.debian +363 -0
- package/dist/server/engine/samples/firewall/iptables/iptables.rules +54 -0
- package/dist/server/engine/samples/firewall/nftables.conf +58 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/dovecot.conf +3 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/iredapd.conf +1 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/mlmmjadmin.conf +1 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/php-fpm.conf +2 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/slapd.conf +1 -0
- package/dist/server/engine/samples/freebsd/syslog.d/dovecot.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/fail2ban.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/iredapd.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/mlmmjadmin.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/php-fpm.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/slapd.conf +2 -0
- package/dist/server/engine/samples/iredmail/iredmail.mysql +491 -0
- package/dist/server/engine/samples/iredmail/iredmail.pgsql +465 -0
- package/dist/server/engine/samples/iredmail/iredmail.schema +456 -0
- package/dist/server/engine/samples/iredmail/used_quota_triggers_dovecot_2.3.pgsql +40 -0
- package/dist/server/engine/samples/iredmail/used_quota_triggers_dovecot_2.4.pgsql +18 -0
- package/dist/server/engine/samples/logrotate/dovecot +13 -0
- package/dist/server/engine/samples/logrotate/iredapd +13 -0
- package/dist/server/engine/samples/logrotate/mlmmjadmin +13 -0
- package/dist/server/engine/samples/logrotate/openldap +19 -0
- package/dist/server/engine/samples/logrotate/php-fpm +13 -0
- package/dist/server/engine/samples/openbsd/ldapd.conf +58 -0
- package/dist/server/engine/samples/openbsd/pf.conf +28 -0
- package/dist/server/engine/samples/postfix/command_filter.pcre +3 -0
- package/dist/server/engine/samples/postfix/freebsd/mailer.conf +9 -0
- package/dist/server/engine/samples/postfix/helo_access.pcre +180 -0
- package/dist/server/engine/samples/postfix/ldap/catchall_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/recipient_bcc_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/recipient_bcc_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/relay_domains.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_bcc_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_bcc_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_dependent_relayhost_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_dependent_relayhost_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_login_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/transport_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/transport_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_alias_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_group_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_group_members_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_mailbox_domains.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_mailbox_maps.cf +12 -0
- package/dist/server/engine/samples/postfix/main.cf +282 -0
- package/dist/server/engine/samples/postfix/main.cf.amavisd +7 -0
- package/dist/server/engine/samples/postfix/main.cf.dovecot +8 -0
- package/dist/server/engine/samples/postfix/main.cf.ldap +39 -0
- package/dist/server/engine/samples/postfix/main.cf.mlmmj +5 -0
- package/dist/server/engine/samples/postfix/main.cf.mysql +39 -0
- package/dist/server/engine/samples/postfix/main.cf.pgsql +39 -0
- package/dist/server/engine/samples/postfix/main.cf.postscreen +30 -0
- package/dist/server/engine/samples/postfix/master.cf +87 -0
- package/dist/server/engine/samples/postfix/mysql/catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/domain_alias_catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/domain_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/recipient_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/recipient_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/relay_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/sender_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/sender_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/sender_dependent_relayhost_maps.cf +6 -0
- package/dist/server/engine/samples/postfix/mysql/sender_login_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/transport_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/transport_maps_maillist.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/transport_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/virtual_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/virtual_mailbox_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/virtual_mailbox_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/domain_alias_catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/domain_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/recipient_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/recipient_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/relay_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_dependent_relayhost_maps.cf +6 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_login_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/transport_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/transport_maps_maillist.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/transport_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/virtual_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/virtual_mailbox_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/virtual_mailbox_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/postscreen_access.cidr +6 -0
- package/dist/server/engine/samples/postgresql/sql/add_first_domain_and_user.sql +34 -0
- package/dist/server/engine/samples/postgresql/sql/grant_permissions.sql +14 -0
- package/dist/server/engine/samples/postgresql/sql/init_vmail_db.sql +15 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-dovecot.conf +23 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-fail2ban.conf +2 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-iredapd.conf +12 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-mlmmjadmin.conf +12 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-openldap.conf +2 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-phpfpm.conf +3 -0
- package/dist/server/engine/samples/spamassassin/local.cf +186 -0
- package/dist/server/engine/samples/spamassassin/razor.conf +1 -0
- package/dist/server/engine/samples/systemd/clamd.service.d/override.conf +2 -0
- package/dist/server/engine/samples/systemd/mariadb.service.d/override.conf +3 -0
- package/dist/server/engine/samples/systemd/slapd.service.d/override.conf +6 -0
- package/dist/server/engine/samples/yum/CentOS-Linux-AppStream.repo +6 -0
- package/dist/server/engine/samples/yum/CentOS-Linux-PowerTools.repo +6 -0
- package/dist/server/engine/samples/yum/CentOS-Stream-AppStream.repo +7 -0
- package/dist/server/engine/samples/yum/CentOS-Stream-PowerTools.repo +7 -0
- package/dist/server/engine/samples/yum/symas-openldap.repo +6 -0
- package/dist/server/engine/tools/add_enabled_service.py +60 -0
- package/dist/server/engine/tools/backup_mysql.sh +238 -0
- package/dist/server/engine/tools/backup_openldap.sh +230 -0
- package/dist/server/engine/tools/backup_pgsql.sh +217 -0
- package/dist/server/engine/tools/backup_sogo.sh +156 -0
- package/dist/server/engine/tools/create_mail_user_OpenLDAP.py +335 -0
- package/dist/server/engine/tools/create_mail_user_OpenLDAP.sh +287 -0
- package/dist/server/engine/tools/create_mail_user_SQL.sh +127 -0
- package/dist/server/engine/tools/enable_postscreen.sh +144 -0
- package/dist/server/engine/tools/fail2ban_unban_ip.sh +39 -0
- package/dist/server/engine/tools/find_sasl_login_ip.sh +20 -0
- package/dist/server/engine/tools/find_top_sasl_usernames.sh +28 -0
- package/dist/server/engine/tools/generate_ssl_keys.sh +85 -0
- package/dist/server/engine/tools/kill_high_cpu_sogo_process.sh +32 -0
- package/dist/server/engine/tools/ldap_assign_user_to_groups.py +151 -0
- package/dist/server/engine/tools/ldap_move_members_to_another_group.py +129 -0
- package/dist/server/engine/tools/migrate_sql_alias_table.py +177 -0
- package/dist/server/engine/update/0.9.8/amavisd.mysql +29 -0
- package/dist/server/engine/update/0.9.8/amavisd.pgsql +39 -0
- package/dist/server/engine/update/0.9.8/iredmail.mysql +53 -0
- package/dist/server/engine/update/0.9.8/iredmail.pgsql +61 -0
- package/dist/server/engine/update/0.9.9/iredmail.mysql +2 -0
- package/dist/server/engine/update/0.9.9/iredmail.pgsql +2 -0
- package/dist/server/engine/update/1.0/iredmail.mysql +2 -0
- package/dist/server/engine/update/1.0/iredmail.pgsql +2 -0
- package/dist/server/engine/update/1.2/last_login.mysql +16 -0
- package/dist/server/engine/update/1.4.0/iredmail.mysql +22 -0
- package/dist/server/engine/update/1.4.0/iredmail.pgsql +20 -0
- package/dist/server/engine/update/1.4.1/iredmail.mysql +3 -0
- package/dist/server/engine/update/1.4.1/iredmail.pgsql +3 -0
- package/dist/server/engine/update/1.4.1/sogo.mysql +11 -0
- package/dist/server/engine/update/1.4.1/sogo.pgsql +30 -0
- package/dist/server/engine/update/1.4.1/update-ldap.py +66 -0
- package/dist/server/engine/update/1.4.2/iredmail.mysql +9 -0
- package/dist/server/engine/update/1.4.2/iredmail.pgsql +9 -0
- package/dist/server/engine/update/1.4.2/sogo.pgsql +30 -0
- package/dist/server/engine/update/1.6.0/sogo_view.pgsql +27 -0
- package/dist/server/engine/update/1.6.3/iredmail.mysql +1 -0
- package/dist/server/engine/update/1.7.0/fail2ban.mysql +11 -0
- package/dist/server/engine/update/1.7.0/fail2ban.pgsql +12 -0
- package/dist/server/engine/update/1.7.1/amavisd.mysql +1 -0
- package/dist/server/engine/update/1.7.2/vmail.mysql +30 -0
- package/dist/server/engine/update/1.7.3/deleted_mailboxes.mysql +43 -0
- package/dist/server/engine/update/1.7.3/iredadmin.mysql +26 -0
- package/dist/server/engine/update/1.7.3/vmail.mysql +79 -0
- package/dist/server/engine/update/1.7.3/vmail.pgsql +9 -0
- package/dist/server/engine/update/README.md +1 -0
- package/dist/server/engine/update/ldap/README.md +40 -0
- package/dist/server/engine/update/ldap/update-ldap-dovecot-2.3.py +69 -0
- package/dist/server/index.js +55793 -53701
- package/dist/server/migrations/0071_gh_device_token.sql +3 -0
- package/dist/server/migrations/0072_gh_device_token_method.sql +1 -0
- package/dist/server/migrations/meta/_journal.json +14 -0
- package/dist/setup-2DMFIA74.js +20 -0
- package/dist/{signin-PVC7MBZJ.js → signin-ITOPKKUB.js} +11 -9
- package/dist/{sso-oidc-ZXY77BSL.js → sso-oidc-NON2PD7Y.js} +11 -9
- package/dist/{sts-LX5L4UU3.js → sts-HHFFSAY2.js} +10 -8
- package/package.json +1 -1
- package/dist/bare-CNSFDNSZ.js +0 -20
- package/dist/cloud-655YYCEW.js +0 -26
- package/dist/docker-UWQPDEGW.js +0 -14
- package/dist/docker-edge-executor-ZLAYE5FE.js +0 -11
- package/dist/edge-import-AFID2EN3.js +0 -41
- package/dist/nginx-M36GDYL7.js +0 -18
- package/dist/setup-ZXXB5S22.js +0 -16
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
|
|
2
3
|
import { createRequire as __ospCreateRequire } from "node:module";
|
|
3
4
|
const require = __ospCreateRequire(import.meta.url);
|
|
4
5
|
import {
|
|
@@ -8,6 +9,9 @@ import {
|
|
|
8
9
|
composeInternalToken,
|
|
9
10
|
composeIsViableDefault,
|
|
10
11
|
composePs,
|
|
12
|
+
composeRestart,
|
|
13
|
+
composeRunning,
|
|
14
|
+
composeStart,
|
|
11
15
|
composeUninstall,
|
|
12
16
|
composeUp,
|
|
13
17
|
composeUpdate,
|
|
@@ -21,47 +25,56 @@ import {
|
|
|
21
25
|
remoteSha,
|
|
22
26
|
shortSha,
|
|
23
27
|
sourceBuildDir
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
29
|
-
import "./chunk-
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
33
|
-
import "./chunk-
|
|
34
|
-
import "./chunk-
|
|
35
|
-
import "./chunk-
|
|
36
|
-
import "./chunk-
|
|
37
|
-
import "./chunk-
|
|
38
|
-
import "./chunk-R74UB4X4.js";
|
|
39
|
-
import "./chunk-3YCMJRDZ.js";
|
|
40
|
-
import "./chunk-7EYFCKZX.js";
|
|
28
|
+
} from "./chunk-IMBD5PZ5.js";
|
|
29
|
+
import "./chunk-FRNAR33O.js";
|
|
30
|
+
import "./chunk-EI575GHN.js";
|
|
31
|
+
import "./chunk-6APIPIJY.js";
|
|
32
|
+
import "./chunk-IXCHURVK.js";
|
|
33
|
+
import "./chunk-OWED2GRM.js";
|
|
34
|
+
import "./chunk-VWPEKOH6.js";
|
|
35
|
+
import "./chunk-W73X43R7.js";
|
|
36
|
+
import "./chunk-TGIINPVM.js";
|
|
37
|
+
import "./chunk-XFCDYZUQ.js";
|
|
38
|
+
import "./chunk-AVIB7CT7.js";
|
|
39
|
+
import "./chunk-5MZ624VX.js";
|
|
40
|
+
import "./chunk-Q2CIRAOK.js";
|
|
41
|
+
import "./chunk-IPYPMI3S.js";
|
|
41
42
|
import {
|
|
42
43
|
beginEdgeTakeover,
|
|
44
|
+
collectProxyCerts,
|
|
43
45
|
completeEdgeTakeover,
|
|
44
46
|
detectInstalledProxy,
|
|
47
|
+
edgeProxy,
|
|
48
|
+
edgeProxyFor,
|
|
45
49
|
foreignProxyOnEdge,
|
|
46
50
|
importSites,
|
|
47
|
-
ourEdgeContainerRunning,
|
|
48
51
|
recoverInterruptedTakeover,
|
|
49
52
|
rollbackEdgeTakeover,
|
|
50
53
|
scanImportableSites
|
|
51
|
-
} from "./chunk-
|
|
52
|
-
import "./chunk-
|
|
53
|
-
import "./chunk-
|
|
54
|
-
import "./chunk-
|
|
55
|
-
import "./chunk-
|
|
56
|
-
import "./chunk-
|
|
54
|
+
} from "./chunk-UXWAVM4C.js";
|
|
55
|
+
import "./chunk-O6ZZF52V.js";
|
|
56
|
+
import "./chunk-JYGD5WSN.js";
|
|
57
|
+
import "./chunk-SJIFLLX4.js";
|
|
58
|
+
import "./chunk-V6AN6XLZ.js";
|
|
59
|
+
import "./chunk-VDMQJHPI.js";
|
|
60
|
+
import "./chunk-MZ2WEHHY.js";
|
|
61
|
+
import "./chunk-L2VOGB2X.js";
|
|
62
|
+
import "./chunk-4Z5QO7N6.js";
|
|
63
|
+
import "./chunk-4TJC4JZQ.js";
|
|
64
|
+
import "./chunk-OXWDY22G.js";
|
|
65
|
+
import "./chunk-RPHRPFEH.js";
|
|
57
66
|
import {
|
|
58
67
|
LocalExecutor
|
|
59
|
-
} from "./chunk-
|
|
60
|
-
import "./chunk-
|
|
61
|
-
import "./chunk-
|
|
62
|
-
import
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
} from "./chunk-TYVME3XD.js";
|
|
69
|
+
import "./chunk-FXTBHTWY.js";
|
|
70
|
+
import "./chunk-FPRHYBY2.js";
|
|
71
|
+
import {
|
|
72
|
+
edgeCrashReason,
|
|
73
|
+
edgeIsServing,
|
|
74
|
+
ourEdgeContainerRunning
|
|
75
|
+
} from "./chunk-R5BHFFAV.js";
|
|
76
|
+
import "./chunk-ILFETZOM.js";
|
|
77
|
+
import "./chunk-VFINNTUL.js";
|
|
65
78
|
import {
|
|
66
79
|
CLOUD_DASHBOARD_URL,
|
|
67
80
|
LOCAL_API_URL,
|
|
@@ -70,9 +83,8 @@ import {
|
|
|
70
83
|
isValidEmail,
|
|
71
84
|
parseOpenshipConfigJson,
|
|
72
85
|
resolveCliUpdatePlan
|
|
73
|
-
} from "./chunk-
|
|
74
|
-
import "./chunk-
|
|
75
|
-
import "./chunk-JWBXYO24.js";
|
|
86
|
+
} from "./chunk-6APULWSU.js";
|
|
87
|
+
import "./chunk-KI2EY3WB.js";
|
|
76
88
|
|
|
77
89
|
// src/index.ts
|
|
78
90
|
import { Command as Command28 } from "commander";
|
|
@@ -474,7 +486,7 @@ import chalk6 from "chalk";
|
|
|
474
486
|
import ora from "ora";
|
|
475
487
|
import { spawn } from "child_process";
|
|
476
488
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
477
|
-
import { createWriteStream as createWriteStream2, existsSync as existsSync7, mkdirSync as mkdirSync8, readFileSync as
|
|
489
|
+
import { createWriteStream as createWriteStream2, existsSync as existsSync7, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
478
490
|
import { dirname as dirname2, join as join8 } from "path";
|
|
479
491
|
import { fileURLToPath } from "url";
|
|
480
492
|
|
|
@@ -1000,20 +1012,10 @@ async function resolvePorts(prefs) {
|
|
|
1000
1012
|
|
|
1001
1013
|
// src/lib/edge-preflight.ts
|
|
1002
1014
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
1003
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync6,
|
|
1015
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
1004
1016
|
import { join as join6 } from "path";
|
|
1005
1017
|
import chalk5 from "chalk";
|
|
1006
1018
|
import { isCancel, log, note, select } from "@clack/prompts";
|
|
1007
|
-
function isSafePath(p) {
|
|
1008
|
-
return /^\/[A-Za-z0-9._/-]+$/.test(p);
|
|
1009
|
-
}
|
|
1010
|
-
function readCertFile(p) {
|
|
1011
|
-
try {
|
|
1012
|
-
return readFileSync4(p, "utf8");
|
|
1013
|
-
} catch {
|
|
1014
|
-
return null;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
1019
|
async function planAndApplyHostEdge(opts, overrides = {}) {
|
|
1018
1020
|
const deps = { ...defaultDeps(), ...overrides };
|
|
1019
1021
|
if (deps.platform !== "linux") return { proceed: true };
|
|
@@ -1031,7 +1033,7 @@ async function planAndApplyHostEdge(opts, overrides = {}) {
|
|
|
1031
1033
|
const { sites, warnings } = await deps.importSites(executor, status);
|
|
1032
1034
|
const action2 = await resolveAction(opts.edge, { status, owner, sites, warnings }, deps);
|
|
1033
1035
|
if (action2 === "cancel") return { proceed: false };
|
|
1034
|
-
const certPems = action2 === "migrate" ?
|
|
1036
|
+
const certPems = action2 === "migrate" ? await deps.collectCerts(executor, sites, { status }) : void 0;
|
|
1035
1037
|
await deps.beginEdgeTakeover(
|
|
1036
1038
|
executor,
|
|
1037
1039
|
status,
|
|
@@ -1108,7 +1110,12 @@ async function offerStoppedProxyImport(executor, deps) {
|
|
|
1108
1110
|
if (!await deps.confirmStoppedImport({ proxy, count: sites.length })) {
|
|
1109
1111
|
return { proceed: true };
|
|
1110
1112
|
}
|
|
1111
|
-
return {
|
|
1113
|
+
return {
|
|
1114
|
+
proceed: true,
|
|
1115
|
+
action: "migrate",
|
|
1116
|
+
sites,
|
|
1117
|
+
certPems: await deps.collectCerts(executor, sites, { proxy })
|
|
1118
|
+
};
|
|
1112
1119
|
}
|
|
1113
1120
|
async function completeHostEdge() {
|
|
1114
1121
|
if (process.platform !== "linux") return;
|
|
@@ -1132,17 +1139,57 @@ async function resolveAction(flag, ctx, deps) {
|
|
|
1132
1139
|
importable: ctx.sites.length
|
|
1133
1140
|
});
|
|
1134
1141
|
}
|
|
1135
|
-
function
|
|
1136
|
-
const
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1142
|
+
async function collectCertsFromProxy(executor, sites, source) {
|
|
1143
|
+
const api = source.proxy ? edgeProxyFor(executor, source.proxy) : await edgeProxy(executor, source.status ? { status: source.status } : {});
|
|
1144
|
+
if (!api) return {};
|
|
1145
|
+
const { certPems, warnings } = await collectProxyCerts(api, sites);
|
|
1146
|
+
for (const w of warnings) console.log(chalk5.yellow(` ${w}`));
|
|
1147
|
+
return certPems;
|
|
1148
|
+
}
|
|
1149
|
+
function renderEdgeConflict(info3) {
|
|
1150
|
+
const { owner, sites, warnings } = info3;
|
|
1151
|
+
if (sites.length > 0) {
|
|
1152
|
+
const lines = sites.map((st) => {
|
|
1153
|
+
const host = (st.serverNames ?? []).join(", ") || "(no server_name)";
|
|
1154
|
+
const dest = st.target.kind === "static" ? `static: ${st.target.root}` : st.target.url;
|
|
1155
|
+
return `${chalk5.bold(host)} \u2192 ${chalk5.dim(dest)}${st.ssl ? chalk5.green(" [TLS]") : ""}`;
|
|
1156
|
+
});
|
|
1157
|
+
note(lines.join("\n"), `Detected ${sites.length} site${sites.length === 1 ? "" : "s"} on ${owner}`);
|
|
1144
1158
|
}
|
|
1145
|
-
|
|
1159
|
+
if (warnings.length > 0) {
|
|
1160
|
+
log.warn(`${warnings.length} config item${warnings.length === 1 ? "" : "s"} won't migrate automatically:`);
|
|
1161
|
+
for (const w of warnings.slice(0, 8)) log.message(chalk5.dim(`\u2022 ${w}`));
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
async function confirmEdgeAction(info3) {
|
|
1165
|
+
const { owner, known, importable } = info3;
|
|
1166
|
+
const choice = await select({
|
|
1167
|
+
message: known ? `An existing reverse proxy (${owner}) is serving ports 80/443.` : `Ports 80/443 are in use by ${owner}, which we couldn't identify.`,
|
|
1168
|
+
options: [
|
|
1169
|
+
...importable > 0 ? [
|
|
1170
|
+
{
|
|
1171
|
+
value: "migrate",
|
|
1172
|
+
label: `Migrate ${importable} site${importable === 1 ? "" : "s"} & take over`,
|
|
1173
|
+
hint: "import the existing sites into Openship's edge, then take 80/443"
|
|
1174
|
+
}
|
|
1175
|
+
] : [],
|
|
1176
|
+
{
|
|
1177
|
+
value: "takeover",
|
|
1178
|
+
label: "Stop it & take over 80/443",
|
|
1179
|
+
hint: known ? "the existing sites stop being served" : "may interrupt a running service"
|
|
1180
|
+
},
|
|
1181
|
+
{ value: "cancel", label: "Cancel \u2014 leave it running" }
|
|
1182
|
+
],
|
|
1183
|
+
// Default to MIGRATE whenever there are sites we can import: it's the only
|
|
1184
|
+
// option that both gets Openship onto 80/443 and keeps the operator's
|
|
1185
|
+
// existing sites served, so it's the choice they almost always want and
|
|
1186
|
+
// the one that loses nothing on a reflexive Enter.
|
|
1187
|
+
// With nothing importable there's no safe default: a known proxy falls
|
|
1188
|
+
// back to cancel (blind Enter would stop sites that are being served),
|
|
1189
|
+
// and an unidentified port holder to takeover.
|
|
1190
|
+
initialValue: importable > 0 ? "migrate" : known ? "cancel" : "takeover"
|
|
1191
|
+
});
|
|
1192
|
+
return isCancel(choice) ? "cancel" : choice;
|
|
1146
1193
|
}
|
|
1147
1194
|
function defaultDeps() {
|
|
1148
1195
|
return {
|
|
@@ -1172,61 +1219,20 @@ function defaultDeps() {
|
|
|
1172
1219
|
});
|
|
1173
1220
|
return !isCancel(take) && take === "import";
|
|
1174
1221
|
},
|
|
1175
|
-
|
|
1176
|
-
render:
|
|
1177
|
-
|
|
1178
|
-
const lines = sites.map((st) => {
|
|
1179
|
-
const host = (st.serverNames ?? []).join(", ") || "(no server_name)";
|
|
1180
|
-
const dest = st.target.kind === "static" ? `static: ${st.target.root}` : st.target.url;
|
|
1181
|
-
return `${chalk5.bold(host)} \u2192 ${chalk5.dim(dest)}${st.ssl ? chalk5.green(" [TLS]") : ""}`;
|
|
1182
|
-
});
|
|
1183
|
-
note(lines.join("\n"), `Detected ${sites.length} site${sites.length === 1 ? "" : "s"} on ${owner}`);
|
|
1184
|
-
}
|
|
1185
|
-
if (warnings.length > 0) {
|
|
1186
|
-
log.warn(`${warnings.length} config item${warnings.length === 1 ? "" : "s"} won't migrate automatically:`);
|
|
1187
|
-
for (const w of warnings.slice(0, 8)) log.message(chalk5.dim(`\u2022 ${w}`));
|
|
1188
|
-
}
|
|
1189
|
-
},
|
|
1190
|
-
confirm: async ({ owner, known, importable }) => {
|
|
1191
|
-
const choice = await select({
|
|
1192
|
-
message: known ? `An existing reverse proxy (${owner}) is serving ports 80/443.` : `Ports 80/443 are in use by ${owner}, which we couldn't identify.`,
|
|
1193
|
-
options: [
|
|
1194
|
-
...importable > 0 ? [
|
|
1195
|
-
{
|
|
1196
|
-
value: "migrate",
|
|
1197
|
-
label: `Migrate ${importable} site${importable === 1 ? "" : "s"} & take over`,
|
|
1198
|
-
hint: "import the existing sites into Openship's edge, then take 80/443"
|
|
1199
|
-
}
|
|
1200
|
-
] : [],
|
|
1201
|
-
{
|
|
1202
|
-
value: "takeover",
|
|
1203
|
-
label: "Stop it & take over 80/443",
|
|
1204
|
-
hint: known ? "the existing sites stop being served" : "may interrupt a running service"
|
|
1205
|
-
},
|
|
1206
|
-
{ value: "cancel", label: "Cancel \u2014 leave it running" }
|
|
1207
|
-
],
|
|
1208
|
-
// Default to MIGRATE whenever there are sites we can import: it's the only
|
|
1209
|
-
// option that both gets Openship onto 80/443 and keeps the operator's
|
|
1210
|
-
// existing sites served, so it's the choice they almost always want and
|
|
1211
|
-
// the one that loses nothing on a reflexive Enter.
|
|
1212
|
-
// With nothing importable there's no safe default: a known proxy falls
|
|
1213
|
-
// back to cancel (blind Enter would stop sites that are being served),
|
|
1214
|
-
// and an unidentified port holder to takeover.
|
|
1215
|
-
initialValue: importable > 0 ? "migrate" : known ? "cancel" : "takeover"
|
|
1216
|
-
});
|
|
1217
|
-
return isCancel(choice) ? "cancel" : choice;
|
|
1218
|
-
},
|
|
1222
|
+
collectCerts: collectCertsFromProxy,
|
|
1223
|
+
render: renderEdgeConflict,
|
|
1224
|
+
confirm: confirmEdgeAction,
|
|
1219
1225
|
warn: (message) => console.log(chalk5.yellow(` ${message}`))
|
|
1220
1226
|
};
|
|
1221
1227
|
}
|
|
1222
1228
|
|
|
1223
1229
|
// src/lib/loopback-api.ts
|
|
1224
|
-
import { existsSync as existsSync6, readFileSync as
|
|
1230
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
1225
1231
|
import { randomBytes } from "crypto";
|
|
1226
1232
|
import { join as join7 } from "path";
|
|
1227
1233
|
function ensureInternalToken() {
|
|
1228
1234
|
const path2 = join7(OS_DIR, "internal-token");
|
|
1229
|
-
if (existsSync6(path2)) return
|
|
1235
|
+
if (existsSync6(path2)) return readFileSync4(path2, "utf8").trim();
|
|
1230
1236
|
mkdirSync7(OS_DIR, { recursive: true, mode: 448 });
|
|
1231
1237
|
const token = randomBytes(32).toString("hex");
|
|
1232
1238
|
writeFileSync6(path2, token, { mode: 384 });
|
|
@@ -1486,26 +1492,31 @@ async function headlessProvision(opts) {
|
|
|
1486
1492
|
warnings.push(`Custom domain provisioning returned: ${res.data?.error || "failed"}`);
|
|
1487
1493
|
}
|
|
1488
1494
|
} else {
|
|
1495
|
+
const freeBody = (s) => ({
|
|
1496
|
+
domainType: "free",
|
|
1497
|
+
slug: s,
|
|
1498
|
+
publicHost: d.publicHost,
|
|
1499
|
+
dashPort,
|
|
1500
|
+
localEdge: d.localEdge,
|
|
1501
|
+
edgeTakeover: d.edgeTakeover,
|
|
1502
|
+
edgeMigrate: d.edgeMigrate
|
|
1503
|
+
});
|
|
1489
1504
|
let slug = d.slug;
|
|
1490
|
-
let res = await internalPost(
|
|
1491
|
-
port,
|
|
1492
|
-
"/api/system/self-register",
|
|
1493
|
-
{ domainType: "free", slug, publicHost: d.publicHost, dashPort },
|
|
1494
|
-
token
|
|
1495
|
-
);
|
|
1505
|
+
let res = await internalPost(port, "/api/system/self-register", freeBody(slug), token);
|
|
1496
1506
|
for (let attempt = 0; !res.ok && isSlugTaken(res.data) && opts.onSlugTaken && attempt < 5; attempt++) {
|
|
1497
1507
|
const next = await opts.onSlugTaken(slug);
|
|
1498
1508
|
if (!next) break;
|
|
1499
1509
|
slug = next;
|
|
1500
|
-
res = await internalPost(
|
|
1501
|
-
port,
|
|
1502
|
-
"/api/system/self-register",
|
|
1503
|
-
{ domainType: "free", slug, publicHost: d.publicHost, dashPort },
|
|
1504
|
-
token
|
|
1505
|
-
);
|
|
1510
|
+
res = await internalPost(port, "/api/system/self-register", freeBody(slug), token);
|
|
1506
1511
|
}
|
|
1507
1512
|
domainRegistered = res.ok;
|
|
1508
1513
|
liveUrl = res.data?.url;
|
|
1514
|
+
if (res.ok && res.data?.sessionId) {
|
|
1515
|
+
const edge = await drainProvisionStream(port, String(res.data.sessionId), token, (m) => log6(` ${m}`));
|
|
1516
|
+
if (!edge.completed && edge.detail) {
|
|
1517
|
+
warnings.push(`Local edge not fully ready: ${edge.detail} \u2014 it retries on next boot.`);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1509
1520
|
if (!res.ok) {
|
|
1510
1521
|
warnings.push(
|
|
1511
1522
|
isSlugTaken(res.data) ? `Free domain not created: "${slug}.opsh.io" is already taken. Re-run and choose a different subdomain, or add one later in Settings \u2192 Domains.` : `Free .opsh.io domain not registered: ${res.data?.error || "failed"}. A free domain needs the box connected to Openship Cloud \u2014 connect it in Settings \u2192 Cloud, or use --domain-kind byo/custom.`
|
|
@@ -1526,6 +1537,12 @@ function normalizeUrl(raw) {
|
|
|
1526
1537
|
return null;
|
|
1527
1538
|
}
|
|
1528
1539
|
}
|
|
1540
|
+
function effectivePublicUrl(flag) {
|
|
1541
|
+
if (flag) return normalizePublicUrl(flag);
|
|
1542
|
+
const saved = readInstanceUrl();
|
|
1543
|
+
if (!saved || /^https?:\/\/(localhost|127\.|\[?::1\]?)([:/]|$)/i.test(saved)) return void 0;
|
|
1544
|
+
return normalizePublicUrl(saved);
|
|
1545
|
+
}
|
|
1529
1546
|
function normalizePublicUrl(raw) {
|
|
1530
1547
|
const url = normalizeUrl(raw);
|
|
1531
1548
|
if (!url) {
|
|
@@ -1541,7 +1558,7 @@ var DIST_DIR = dirname2(fileURLToPath(import.meta.url));
|
|
|
1541
1558
|
var SERVER_DIR = join8(DIST_DIR, "server");
|
|
1542
1559
|
function ensureAuthSecret() {
|
|
1543
1560
|
const path2 = join8(OS_DIR, "auth-secret");
|
|
1544
|
-
if (existsSync7(path2)) return
|
|
1561
|
+
if (existsSync7(path2)) return readFileSync5(path2, "utf8").trim();
|
|
1545
1562
|
mkdirSync8(OS_DIR, { recursive: true, mode: 448 });
|
|
1546
1563
|
const secret = randomBytes2(32).toString("hex");
|
|
1547
1564
|
writeFileSync7(path2, secret, { mode: 384 });
|
|
@@ -1683,7 +1700,7 @@ async function runCompose(opts) {
|
|
|
1683
1700
|
);
|
|
1684
1701
|
process.exit(1);
|
|
1685
1702
|
}
|
|
1686
|
-
const publicUrl =
|
|
1703
|
+
const publicUrl = effectivePublicUrl(opts.publicUrl);
|
|
1687
1704
|
const fromSource = sourceBuildDir();
|
|
1688
1705
|
const spinner5 = ora(
|
|
1689
1706
|
fromSource ? `Building Openship from ${fromSource} and starting the stack\u2026` : "Starting Openship via Docker Compose\u2026"
|
|
@@ -1693,8 +1710,10 @@ async function runCompose(opts) {
|
|
|
1693
1710
|
dashboardPort: opts.dashboardPort,
|
|
1694
1711
|
publicUrl,
|
|
1695
1712
|
trustProxy: opts.trustProxy,
|
|
1696
|
-
// commander maps `--no-host-control` to hostControl === false.
|
|
1697
|
-
|
|
1713
|
+
// commander maps `--no-host-control` to hostControl === false. `undefined` when
|
|
1714
|
+
// the flag is absent, so a plain re-run keeps the install's original choice
|
|
1715
|
+
// instead of silently re-granting host control (see resolveEnvConfig).
|
|
1716
|
+
noHostControl: opts.hostControl === false ? true : void 0
|
|
1698
1717
|
});
|
|
1699
1718
|
if (!res.ok) {
|
|
1700
1719
|
spinner5.fail("docker compose failed to start the stack");
|
|
@@ -1705,6 +1724,27 @@ async function runCompose(opts) {
|
|
|
1705
1724
|
process.exit(1);
|
|
1706
1725
|
}
|
|
1707
1726
|
spinner5.succeed("Openship is running via Docker Compose.");
|
|
1727
|
+
if (edgePlan.action && !await edgeIsServing(new LocalExecutor())) {
|
|
1728
|
+
const reason = await edgeCrashReason(new LocalExecutor());
|
|
1729
|
+
console.error(
|
|
1730
|
+
chalk6.red(`
|
|
1731
|
+
Openship's edge is not serving :80${reason ? ` \u2014 ${reason}` : "."}`)
|
|
1732
|
+
);
|
|
1733
|
+
const restored = await rollbackHostEdge();
|
|
1734
|
+
console.error(
|
|
1735
|
+
restored ? chalk6.yellow(
|
|
1736
|
+
` Your previous proxy has been restarted \u2014 the box is serving again, on it.
|
|
1737
|
+
Nothing was migrated. Fix the cause above, then re-run \`openship up\`.
|
|
1738
|
+
`
|
|
1739
|
+
) : chalk6.red(
|
|
1740
|
+
` AND your previous proxy could NOT be restarted automatically \u2014 the box is
|
|
1741
|
+
serving nothing right now. Start it by hand:
|
|
1742
|
+
docker stop openship-edge && sudo systemctl enable --now nginx
|
|
1743
|
+
`
|
|
1744
|
+
)
|
|
1745
|
+
);
|
|
1746
|
+
process.exit(1);
|
|
1747
|
+
}
|
|
1708
1748
|
let importedOk = true;
|
|
1709
1749
|
if (edgePlan.action === "migrate" && edgePlan.sites?.length) {
|
|
1710
1750
|
const outcome = await importMigratedSites(res.apiPort, edgePlan.sites, edgePlan.certPems);
|
|
@@ -1742,7 +1782,7 @@ async function runFromSource(opts) {
|
|
|
1742
1782
|
await runForeground(opts, src);
|
|
1743
1783
|
}
|
|
1744
1784
|
async function startService(opts, runOpts = {}) {
|
|
1745
|
-
const publicUrl =
|
|
1785
|
+
const publicUrl = effectivePublicUrl(opts.publicUrl);
|
|
1746
1786
|
if (opts.dryRun) {
|
|
1747
1787
|
const p = preview({
|
|
1748
1788
|
port: opts.port,
|
|
@@ -1841,7 +1881,7 @@ async function runForeground(opts, source) {
|
|
|
1841
1881
|
});
|
|
1842
1882
|
const port = String(resolved.api);
|
|
1843
1883
|
const dashPort = String(resolved.dashboard);
|
|
1844
|
-
const publicUrl =
|
|
1884
|
+
const publicUrl = effectivePublicUrl(opts.publicUrl);
|
|
1845
1885
|
const managedEdge = Boolean(opts.managedEdge && publicUrl);
|
|
1846
1886
|
const dataDir = opts.dataDir || join8(OS_DIR, "data");
|
|
1847
1887
|
mkdirSync8(dataDir, { recursive: true });
|
|
@@ -1863,9 +1903,12 @@ async function runForeground(opts, source) {
|
|
|
1863
1903
|
if (!source) {
|
|
1864
1904
|
env.OPENSHIP_MIGRATIONS_DIR = join8(SERVER_DIR, "migrations");
|
|
1865
1905
|
env.OPENSHIP_PGLITE_ASSETS_DIR = join8(SERVER_DIR, "pglite");
|
|
1906
|
+
const engineDir = join8(SERVER_DIR, "engine");
|
|
1907
|
+
if (existsSync7(engineDir)) env.MAIL_SERVER_ENGINE_DIR = engineDir;
|
|
1866
1908
|
}
|
|
1867
1909
|
env.OPENSHIP_REQUIRE_AUTH = "true";
|
|
1868
1910
|
env.INTERNAL_TOKEN = ensureInternalToken();
|
|
1911
|
+
if (!env.OPENSHIP_AUTH_MODE) env.OPENSHIP_AUTH_MODE = "local";
|
|
1869
1912
|
env.OPENSHIP_API_HOST = "127.0.0.1";
|
|
1870
1913
|
env.OPENSHIP_DASHBOARD_PORT = dashPort;
|
|
1871
1914
|
env.OPENSHIP_INSTANCE_LOG = instanceLogPath;
|
|
@@ -1953,7 +1996,7 @@ async function runForeground(opts, source) {
|
|
|
1953
1996
|
const uiSpinner = ora("Preparing the dashboard\u2026").start();
|
|
1954
1997
|
try {
|
|
1955
1998
|
const bundle = await ensureDashboard({
|
|
1956
|
-
tag: source ? "local" : opts.uiVersion || `v${"0.4.
|
|
1999
|
+
tag: source ? "local" : opts.uiVersion || `v${"0.4.7"}`,
|
|
1957
2000
|
onProgress: (received, total) => {
|
|
1958
2001
|
if (total) {
|
|
1959
2002
|
uiSpinner.text = `Downloading dashboard\u2026 ${Math.round(received / total * 100)}%`;
|
|
@@ -2222,7 +2265,7 @@ var initCommand = new Command7("init").description("Link the current directory t
|
|
|
2222
2265
|
|
|
2223
2266
|
// src/commands/config.ts
|
|
2224
2267
|
import { Command as Command8 } from "commander";
|
|
2225
|
-
import { existsSync as existsSync10, readFileSync as
|
|
2268
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6, writeFileSync as writeFileSync9 } from "fs";
|
|
2226
2269
|
import { join as join10 } from "path";
|
|
2227
2270
|
var SCHEMA_URL = "https://openship.io/openship.schema.json";
|
|
2228
2271
|
var CONFIG_FILE = "openship.json";
|
|
@@ -2243,7 +2286,7 @@ function detectHints(dir) {
|
|
|
2243
2286
|
const pkgPath = join10(dir, "package.json");
|
|
2244
2287
|
if (existsSync10(pkgPath)) {
|
|
2245
2288
|
try {
|
|
2246
|
-
const pkg = JSON.parse(
|
|
2289
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
2247
2290
|
const runner = hints.packageManager ?? "npm";
|
|
2248
2291
|
const exec = runner === "npm" ? "npm run" : runner;
|
|
2249
2292
|
if (pkg.scripts?.build) hints.buildCommand = `${exec} build`;
|
|
@@ -2279,7 +2322,7 @@ var validateCmd = new Command8("validate").description("Validate an openship.jso
|
|
|
2279
2322
|
else err(`Not found: ${path2}`);
|
|
2280
2323
|
process.exit(1);
|
|
2281
2324
|
}
|
|
2282
|
-
const { config, errors, warnings } = parseOpenshipConfigJson(
|
|
2325
|
+
const { config, errors, warnings } = parseOpenshipConfigJson(readFileSync6(path2, "utf8"));
|
|
2283
2326
|
const valid = errors.length === 0 && config !== null;
|
|
2284
2327
|
if (isJsonMode()) {
|
|
2285
2328
|
printJson({ valid, errors, warnings });
|
|
@@ -2352,11 +2395,11 @@ var contextCommand = new Command9("context").alias("ctx").description("Manage co
|
|
|
2352
2395
|
// src/commands/status.ts
|
|
2353
2396
|
import { Command as Command10 } from "commander";
|
|
2354
2397
|
import chalk9 from "chalk";
|
|
2355
|
-
import { readFileSync as
|
|
2398
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
2356
2399
|
import { join as join11 } from "path";
|
|
2357
2400
|
function readPorts() {
|
|
2358
2401
|
try {
|
|
2359
|
-
return JSON.parse(
|
|
2402
|
+
return JSON.parse(readFileSync7(join11(OS_DIR, "ports.json"), "utf8"));
|
|
2360
2403
|
} catch {
|
|
2361
2404
|
return {};
|
|
2362
2405
|
}
|
|
@@ -2420,7 +2463,7 @@ import { intro, outro, note as note2, select as select3, log as log3, spinner as
|
|
|
2420
2463
|
|
|
2421
2464
|
// src/lib/repair.ts
|
|
2422
2465
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
2423
|
-
import { existsSync as existsSync12, readFileSync as
|
|
2466
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
|
|
2424
2467
|
import { join as join13 } from "path";
|
|
2425
2468
|
import chalk10 from "chalk";
|
|
2426
2469
|
import { spinner, log as log2, select as select2, isCancel as isCancel3, cancel } from "@clack/prompts";
|
|
@@ -2534,7 +2577,7 @@ function ensure(value) {
|
|
|
2534
2577
|
function storedPorts() {
|
|
2535
2578
|
try {
|
|
2536
2579
|
const p = join13(OS_DIR, "ports.json");
|
|
2537
|
-
return existsSync12(p) ? JSON.parse(
|
|
2580
|
+
return existsSync12(p) ? JSON.parse(readFileSync8(p, "utf8")) : {};
|
|
2538
2581
|
} catch {
|
|
2539
2582
|
return {};
|
|
2540
2583
|
}
|
|
@@ -2586,7 +2629,7 @@ function lastServiceError() {
|
|
|
2586
2629
|
const p = join13(LOG_DIR2, name);
|
|
2587
2630
|
if (!existsSync12(p)) continue;
|
|
2588
2631
|
try {
|
|
2589
|
-
const lines =
|
|
2632
|
+
const lines = readFileSync8(p, "utf8").trim().split("\n");
|
|
2590
2633
|
const hit = [...lines].reverse().find((l) => /error|locked|aborted|malformed|corrupt|throw|cannot|EADDRINUSE/i.test(l));
|
|
2591
2634
|
if (hit) return hit.trim().slice(0, 240);
|
|
2592
2635
|
} catch {
|
|
@@ -3013,7 +3056,7 @@ import { execFileSync as execFileSync4 } from "child_process";
|
|
|
3013
3056
|
import ora2 from "ora";
|
|
3014
3057
|
|
|
3015
3058
|
// src/lib/project-link.ts
|
|
3016
|
-
import { readFileSync as
|
|
3059
|
+
import { readFileSync as readFileSync9, existsSync as existsSync14 } from "fs";
|
|
3017
3060
|
import { join as join14, dirname as dirname3, parse } from "path";
|
|
3018
3061
|
var LINK_REL = join14(".openship", "project.json");
|
|
3019
3062
|
function findProjectLinkPath(from = process.cwd()) {
|
|
@@ -3030,7 +3073,7 @@ function readProjectLink(from) {
|
|
|
3030
3073
|
const path2 = findProjectLinkPath(from);
|
|
3031
3074
|
if (!path2) return null;
|
|
3032
3075
|
try {
|
|
3033
|
-
return JSON.parse(
|
|
3076
|
+
return JSON.parse(readFileSync9(path2, "utf8"));
|
|
3034
3077
|
} catch {
|
|
3035
3078
|
return null;
|
|
3036
3079
|
}
|
|
@@ -3038,7 +3081,7 @@ function readProjectLink(from) {
|
|
|
3038
3081
|
|
|
3039
3082
|
// src/lib/folder-deploy.ts
|
|
3040
3083
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
3041
|
-
import { readFileSync as
|
|
3084
|
+
import { readFileSync as readFileSync10, existsSync as existsSync15, rmSync as rmSync4 } from "fs";
|
|
3042
3085
|
import { tmpdir } from "os";
|
|
3043
3086
|
import { join as join15, basename } from "path";
|
|
3044
3087
|
function detectPackageManager(dir) {
|
|
@@ -3088,7 +3131,7 @@ async function deployFolder(opts) {
|
|
|
3088
3131
|
);
|
|
3089
3132
|
step("Uploading source");
|
|
3090
3133
|
try {
|
|
3091
|
-
const body =
|
|
3134
|
+
const body = readFileSync10(tarball);
|
|
3092
3135
|
const up = session.upload;
|
|
3093
3136
|
const method = up.method || "POST";
|
|
3094
3137
|
const res = /^https?:\/\//i.test(up.url) ? await fetch(up.url, { method, headers: up.headers, body }) : await apiRaw(`/${up.url.replace(/^\/+/, "")}`, { method, headers: up.headers, body });
|
|
@@ -4800,7 +4843,7 @@ var domainCommand = new Command17("domain").description("Manage custom domains,
|
|
|
4800
4843
|
import { Command as Command18 } from "commander";
|
|
4801
4844
|
import chalk15 from "chalk";
|
|
4802
4845
|
import ora4 from "ora";
|
|
4803
|
-
var INSTALLABLE = ["docker", "git", "
|
|
4846
|
+
var INSTALLABLE = ["docker", "git", "edge", "rsync"];
|
|
4804
4847
|
function guard(fn) {
|
|
4805
4848
|
return async (...args) => {
|
|
4806
4849
|
if (!getToken()) {
|
|
@@ -5094,7 +5137,7 @@ var serverCommand = server;
|
|
|
5094
5137
|
// src/commands/system.ts
|
|
5095
5138
|
import { Command as Command19 } from "commander";
|
|
5096
5139
|
import ora5 from "ora";
|
|
5097
|
-
import { readFileSync as
|
|
5140
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
5098
5141
|
import { createInterface as createInterface6 } from "readline/promises";
|
|
5099
5142
|
import { stdin as input5, stdout as output5 } from "process";
|
|
5100
5143
|
async function guarded(fn) {
|
|
@@ -5420,7 +5463,7 @@ dataTransferCommand.command("import").description("Import an instance export fil
|
|
|
5420
5463
|
}
|
|
5421
5464
|
let file;
|
|
5422
5465
|
try {
|
|
5423
|
-
file = JSON.parse(
|
|
5466
|
+
file = JSON.parse(readFileSync11(opts.file, "utf8"));
|
|
5424
5467
|
} catch {
|
|
5425
5468
|
err(`
|
|
5426
5469
|
Could not read or parse ${opts.file}.
|
|
@@ -5771,7 +5814,7 @@ var mailCommand = new Command20("mail").description("Self-hosted mail server (iR
|
|
|
5771
5814
|
// src/commands/backup.ts
|
|
5772
5815
|
import { Command as Command21 } from "commander";
|
|
5773
5816
|
import ora7 from "ora";
|
|
5774
|
-
import { readFileSync as
|
|
5817
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
5775
5818
|
async function guard3(fn) {
|
|
5776
5819
|
try {
|
|
5777
5820
|
await fn();
|
|
@@ -6064,7 +6107,7 @@ destinationCmd.command("create").description("Create a backup destination").requ
|
|
|
6064
6107
|
let sftpPrivateKey = opts.sftpPrivateKey;
|
|
6065
6108
|
if (opts.sftpPrivateKeyFile) {
|
|
6066
6109
|
try {
|
|
6067
|
-
sftpPrivateKey =
|
|
6110
|
+
sftpPrivateKey = readFileSync12(opts.sftpPrivateKeyFile, "utf8");
|
|
6068
6111
|
} catch {
|
|
6069
6112
|
throw new Error(`Cannot read key file: ${opts.sftpPrivateKeyFile}`);
|
|
6070
6113
|
}
|
|
@@ -6256,11 +6299,11 @@ var apiCommand = new Command23("api").description("Make an authenticated request
|
|
|
6256
6299
|
import { Command as Command24 } from "commander";
|
|
6257
6300
|
import chalk19 from "chalk";
|
|
6258
6301
|
import { intro as intro2, outro as outro2, password as passwordPrompt, isCancel as isCancel4, cancel as cancel3, log as log4 } from "@clack/prompts";
|
|
6259
|
-
import { readFileSync as
|
|
6302
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
6260
6303
|
import { join as join16 } from "path";
|
|
6261
6304
|
function resolvedApiPort() {
|
|
6262
6305
|
try {
|
|
6263
|
-
return JSON.parse(
|
|
6306
|
+
return JSON.parse(readFileSync13(join16(OS_DIR, "ports.json"), "utf8")).api;
|
|
6264
6307
|
} catch {
|
|
6265
6308
|
return void 0;
|
|
6266
6309
|
}
|
|
@@ -6314,7 +6357,7 @@ var resetAdminCommand = new Command24("reset-admin-password").description("Reset
|
|
|
6314
6357
|
|
|
6315
6358
|
// src/commands/install.ts
|
|
6316
6359
|
import { Command as Command25 } from "commander";
|
|
6317
|
-
import { chmodSync as chmodSync2, existsSync as existsSync16, mkdirSync as mkdirSync11, readFileSync as
|
|
6360
|
+
import { chmodSync as chmodSync2, existsSync as existsSync16, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
|
|
6318
6361
|
import { spawn as spawn2, spawnSync as spawnSync6 } from "child_process";
|
|
6319
6362
|
import { homedir as homedir3 } from "os";
|
|
6320
6363
|
import { join as join17 } from "path";
|
|
@@ -6451,7 +6494,7 @@ var installCommand = new Command25("install").description("Download and install
|
|
|
6451
6494
|
try {
|
|
6452
6495
|
let sidecarBody;
|
|
6453
6496
|
if (existsSync16(sidecarPath) && !downloaded) {
|
|
6454
|
-
sidecarBody =
|
|
6497
|
+
sidecarBody = readFileSync14(sidecarPath, "utf8");
|
|
6455
6498
|
} else {
|
|
6456
6499
|
sidecarBody = await fetchSidecar(sidecarUrl);
|
|
6457
6500
|
}
|
|
@@ -6562,7 +6605,7 @@ function detectPackageManager2(override) {
|
|
|
6562
6605
|
var updateCommand = new Command26("update").description("Update the Openship CLI + bundled server to the latest release").option("--check", "Only report the current + latest version; don't install").option("--via <manager>", "Package manager to update with: bun | npm").option("--rebuild", "From-source installs: rebuild even if already at the remote tip").action(async (opts) => {
|
|
6563
6606
|
const source = readSourceInstall();
|
|
6564
6607
|
if (source) return runSourceUpdate(source, opts);
|
|
6565
|
-
const current = "0.4.
|
|
6608
|
+
const current = "0.4.7";
|
|
6566
6609
|
let latest;
|
|
6567
6610
|
try {
|
|
6568
6611
|
latest = (await resolveLatestTag()).replace(/^v/, "");
|
|
@@ -6597,13 +6640,13 @@ var updateCommand = new Command26("update").description("Update the Openship CLI
|
|
|
6597
6640
|
return;
|
|
6598
6641
|
}
|
|
6599
6642
|
if (readInstallMethod() === "compose") {
|
|
6600
|
-
const
|
|
6643
|
+
const applied = composeUpdate(latest);
|
|
6601
6644
|
if (isJsonMode()) {
|
|
6602
|
-
printJson({ updated: true, from: current, to: latest, via: pm, method: "compose",
|
|
6603
|
-
} else if (
|
|
6604
|
-
ok(`Updated to v${latest}
|
|
6645
|
+
printJson({ updated: true, from: current, to: latest, via: pm, method: "compose", applied });
|
|
6646
|
+
} else if (applied) {
|
|
6647
|
+
ok(`Updated to v${latest} \u2014 compose stack regenerated, images pulled, services recreated.`);
|
|
6605
6648
|
} else {
|
|
6606
|
-
err(`Updated the CLI to v${latest}, but
|
|
6649
|
+
err(`Updated the CLI to v${latest}, but bringing the compose stack up failed. Re-run \`openship update\`, or \`openship up\` to retry.`);
|
|
6607
6650
|
process.exitCode = 1;
|
|
6608
6651
|
}
|
|
6609
6652
|
return;
|
|
@@ -6620,7 +6663,7 @@ var updateCommand = new Command26("update").description("Update the Openship CLI
|
|
|
6620
6663
|
|
|
6621
6664
|
// src/commands/cache.ts
|
|
6622
6665
|
import { Command as Command27 } from "commander";
|
|
6623
|
-
import { existsSync as existsSync17, readdirSync as readdirSync2, readFileSync as
|
|
6666
|
+
import { existsSync as existsSync17, readdirSync as readdirSync2, readFileSync as readFileSync15, rmSync as rmSync5, statSync as statSync2 } from "fs";
|
|
6624
6667
|
import { join as join18 } from "path";
|
|
6625
6668
|
function listAssets() {
|
|
6626
6669
|
if (!existsSync17(RELEASES_DIR)) return [];
|
|
@@ -6669,7 +6712,7 @@ var verifyCmd2 = new Command27("verify").description("Re-hash cached assets and
|
|
|
6669
6712
|
results.push({ tag: a.tag, asset: a.name, result: "no-sidecar" });
|
|
6670
6713
|
continue;
|
|
6671
6714
|
}
|
|
6672
|
-
const expected = parseSha256(
|
|
6715
|
+
const expected = parseSha256(readFileSync15(`${a.path}.sha256`, "utf8"));
|
|
6673
6716
|
const actual = await hashFile(a.path);
|
|
6674
6717
|
const okMatch = expected !== null && expected === actual;
|
|
6675
6718
|
if (!okMatch) bad += 1;
|
|
@@ -6705,7 +6748,7 @@ var cacheCommand = new Command27("cache").description("Manage the local download
|
|
|
6705
6748
|
import chalk20 from "chalk";
|
|
6706
6749
|
import open2 from "open";
|
|
6707
6750
|
import { createHash as createHash2, randomBytes as randomBytes3 } from "crypto";
|
|
6708
|
-
import { existsSync as existsSync18, mkdirSync as mkdirSync12, readFileSync as
|
|
6751
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync12, readFileSync as readFileSync16, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "fs";
|
|
6709
6752
|
import { join as join19 } from "path";
|
|
6710
6753
|
import {
|
|
6711
6754
|
intro as intro3,
|
|
@@ -6893,6 +6936,21 @@ ${pad("Login")}${opts.adminEmail} ${chalk20.dim("(email + password you set)")}
|
|
|
6893
6936
|
);
|
|
6894
6937
|
outro3(opts.byo ? chalk20.dim("Point your reverse proxy at the dashboard port above.") : chalk20.green("Happy shipping."));
|
|
6895
6938
|
}
|
|
6939
|
+
async function promptLocalEdgeTakeover(port) {
|
|
6940
|
+
const pf = await internalPost(port, "/api/system/self-edge/preflight", {});
|
|
6941
|
+
const status = pf.ok ? pf.data?.status : void 0;
|
|
6942
|
+
if (!status || status.canProceedClean || !status.occupants?.length) {
|
|
6943
|
+
return { proceed: true, edgeMigrate: false, edgeTakeover: false };
|
|
6944
|
+
}
|
|
6945
|
+
const owner = status.occupants.map((o) => o.command ?? `port ${o.port}`).join(", ");
|
|
6946
|
+
const known = status.classification === "known";
|
|
6947
|
+
const sites = pf.ok && Array.isArray(pf.data?.sites) ? pf.data.sites : [];
|
|
6948
|
+
const warnings = pf.ok && Array.isArray(pf.data?.warnings) ? pf.data.warnings : [];
|
|
6949
|
+
renderEdgeConflict({ owner, sites, warnings });
|
|
6950
|
+
const action2 = await confirmEdgeAction({ owner, known, importable: sites.length });
|
|
6951
|
+
if (action2 === "cancel") return { proceed: false, edgeMigrate: false, edgeTakeover: false };
|
|
6952
|
+
return { proceed: true, edgeMigrate: action2 === "migrate", edgeTakeover: action2 === "takeover" };
|
|
6953
|
+
}
|
|
6896
6954
|
async function runWizard() {
|
|
6897
6955
|
const resuming = isSetupInProgress();
|
|
6898
6956
|
intro3(`${chalk20.bgCyan(chalk20.black(" Openship "))}${chalk20.dim(" setup")}`);
|
|
@@ -7114,7 +7172,7 @@ async function runWizard() {
|
|
|
7114
7172
|
}
|
|
7115
7173
|
}
|
|
7116
7174
|
}
|
|
7117
|
-
const uiTag = `v${"0.4.
|
|
7175
|
+
const uiTag = `v${"0.4.7"}`;
|
|
7118
7176
|
if (method === "bare") {
|
|
7119
7177
|
const dl = spinner4();
|
|
7120
7178
|
dl.start("Pulling the Openship dist from GitHub");
|
|
@@ -7182,7 +7240,7 @@ async function runWizard() {
|
|
|
7182
7240
|
const up = composeUp({
|
|
7183
7241
|
publicUrl,
|
|
7184
7242
|
trustProxy: behindProxy,
|
|
7185
|
-
version: "0.4.
|
|
7243
|
+
version: "0.4.7",
|
|
7186
7244
|
noHostControl: !allowHostControl
|
|
7187
7245
|
});
|
|
7188
7246
|
if (!up.ok) {
|
|
@@ -7319,93 +7377,49 @@ async function runWizard() {
|
|
|
7319
7377
|
await internalPost(port, "/api/system/self-register", { domainType: "byo" });
|
|
7320
7378
|
} else {
|
|
7321
7379
|
cloudEmail = cloud.email;
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
const res = await internalPost(port, "/api/system/self-register", {
|
|
7327
|
-
domainType: "free",
|
|
7328
|
-
slug: regSlug,
|
|
7329
|
-
publicHost: domainPlan.publicHost,
|
|
7330
|
-
dashPort: Number(started.dashPort)
|
|
7331
|
-
});
|
|
7332
|
-
if (res.ok && res.data?.url) {
|
|
7333
|
-
liveUrl = res.data.url;
|
|
7334
|
-
s2.stop(`Free domain live: ${res.data.url}`);
|
|
7335
|
-
break;
|
|
7336
|
-
}
|
|
7337
|
-
s2.stop(`Couldn't register ${regSlug}.opsh.io: ${res.data?.error || "failed"}`, 1);
|
|
7338
|
-
const next = ensure2(
|
|
7339
|
-
await select4({
|
|
7340
|
-
message: "Try a different subdomain?",
|
|
7341
|
-
options: [
|
|
7342
|
-
{ value: "retry", label: "Pick another subdomain" },
|
|
7343
|
-
{ value: "skip", label: "Skip for now", hint: "log in on this server; add a domain later in Settings \u2192 Cloud" }
|
|
7344
|
-
]
|
|
7345
|
-
})
|
|
7380
|
+
const edge = await promptLocalEdgeTakeover(port);
|
|
7381
|
+
if (!edge.proceed) {
|
|
7382
|
+
log5.warn(
|
|
7383
|
+
"Left the existing proxy on 80/443 running \u2014 a free domain forwards to :80 here, so it won't serve until Openship owns that port. Re-run setup and choose migrate / take over."
|
|
7346
7384
|
);
|
|
7347
|
-
if (next === "skip") break;
|
|
7348
|
-
regSlug = ensure2(
|
|
7349
|
-
await text({
|
|
7350
|
-
message: "Choose your subdomain",
|
|
7351
|
-
placeholder: "my-openship",
|
|
7352
|
-
initialValue: regSlug,
|
|
7353
|
-
validate: (v) => v && SLUG_RE2.test(v.trim().toLowerCase()) ? void 0 : "Lowercase letters, digits, hyphens"
|
|
7354
|
-
})
|
|
7355
|
-
).trim().toLowerCase();
|
|
7356
7385
|
}
|
|
7386
|
+
const result = await headlessProvision({
|
|
7387
|
+
port,
|
|
7388
|
+
dashPort: started.dashPort,
|
|
7389
|
+
token: provisionToken,
|
|
7390
|
+
method: "bare",
|
|
7391
|
+
inputs: {
|
|
7392
|
+
admin,
|
|
7393
|
+
domain: {
|
|
7394
|
+
kind: "free",
|
|
7395
|
+
slug: domainPlan.slug,
|
|
7396
|
+
publicHost: domainPlan.publicHost,
|
|
7397
|
+
// Bare needs a local :80 edge for Cloud to forward to; skip only when
|
|
7398
|
+
// the operator declined the takeover (their proxy keeps 80/443).
|
|
7399
|
+
localEdge: edge.proceed,
|
|
7400
|
+
edgeTakeover: edge.edgeTakeover,
|
|
7401
|
+
edgeMigrate: edge.edgeMigrate
|
|
7402
|
+
}
|
|
7403
|
+
},
|
|
7404
|
+
onLog: (msg) => log5.message(chalk20.dim(msg)),
|
|
7405
|
+
onSlugTaken: async (taken) => {
|
|
7406
|
+
log5.warn(`"${taken}.opsh.io" is already taken.`);
|
|
7407
|
+
const next = await text({
|
|
7408
|
+
message: "Choose a different subdomain (or leave empty to skip the free domain)",
|
|
7409
|
+
placeholder: "my-openship",
|
|
7410
|
+
validate: (v) => !v || SLUG_RE2.test(v.trim().toLowerCase()) ? void 0 : "Lowercase letters, digits, hyphens"
|
|
7411
|
+
});
|
|
7412
|
+
return isCancel5(next) || !next.trim() ? null : next.trim().toLowerCase();
|
|
7413
|
+
}
|
|
7414
|
+
});
|
|
7415
|
+
if (result.liveUrl) liveUrl = result.liveUrl;
|
|
7416
|
+
for (const w of result.warnings) log5.warn(w);
|
|
7357
7417
|
}
|
|
7358
7418
|
} else if (domainPlan.type === "custom") {
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
const
|
|
7363
|
-
const status = pf.ok ? pf.data?.status : void 0;
|
|
7364
|
-
const importable = pf.ok && Array.isArray(pf.data?.sites) ? pf.data.sites.length : 0;
|
|
7365
|
-
if (status && !status.canProceedClean && status.occupants?.length) {
|
|
7366
|
-
const owner = status.occupants.map((o) => o.command ?? `port ${o.port}`).join(", ");
|
|
7367
|
-
const known = status.classification === "known";
|
|
7368
|
-
const sites = pf.ok && Array.isArray(pf.data?.sites) ? pf.data.sites : [];
|
|
7369
|
-
if (sites.length > 0) {
|
|
7370
|
-
const lines = sites.map((st) => {
|
|
7371
|
-
const host = (st.serverNames ?? []).join(", ") || "(no server_name)";
|
|
7372
|
-
const dest = st.target?.kind === "static" ? `static: ${st.target?.root ?? ""}` : st.target?.url ?? "";
|
|
7373
|
-
return `${chalk20.bold(host)} \u2192 ${chalk20.dim(dest)}${st.ssl ? chalk20.green(" [TLS]") : ""}`;
|
|
7374
|
-
});
|
|
7375
|
-
note3(lines.join("\n"), `Detected ${sites.length} site${sites.length === 1 ? "" : "s"} on ${owner}`);
|
|
7376
|
-
}
|
|
7377
|
-
const warns = pf.ok && Array.isArray(pf.data?.warnings) ? pf.data.warnings : [];
|
|
7378
|
-
if (warns.length > 0) {
|
|
7379
|
-
log5.warn(`${warns.length} config item${warns.length === 1 ? "" : "s"} won't migrate automatically:`);
|
|
7380
|
-
for (const w of warns.slice(0, 8)) log5.message(chalk20.dim(`\u2022 ${w}`));
|
|
7381
|
-
}
|
|
7382
|
-
const choice = ensure2(
|
|
7383
|
-
await select4({
|
|
7384
|
-
message: known ? `An existing reverse proxy (${owner}) is serving ports 80/443.` : `Ports 80/443 are in use by ${owner}, which we couldn't identify.`,
|
|
7385
|
-
options: [
|
|
7386
|
-
...importable > 0 ? [{
|
|
7387
|
-
value: "migrate",
|
|
7388
|
-
label: `Migrate ${importable} site${importable === 1 ? "" : "s"} & take over`,
|
|
7389
|
-
hint: "import the existing sites into Openship, then take 80/443"
|
|
7390
|
-
}] : [],
|
|
7391
|
-
{
|
|
7392
|
-
value: "override",
|
|
7393
|
-
label: "Stop it & take over 80/443",
|
|
7394
|
-
hint: known ? "the existing sites stop being served" : "may interrupt a running service"
|
|
7395
|
-
},
|
|
7396
|
-
{ value: "cancel", label: "Cancel \u2014 leave it running" }
|
|
7397
|
-
],
|
|
7398
|
-
// Same default as the `up` preflight (edge-preflight.ts): migrate when
|
|
7399
|
-
// there are importable sites — it takes 80/443 without dropping any of
|
|
7400
|
-
// them. Otherwise a known proxy defaults to cancel (Enter must not stop
|
|
7401
|
-
// sites that are being served) and an unidentified holder to takeover.
|
|
7402
|
-
initialValue: importable > 0 ? "migrate" : known ? "cancel" : "override"
|
|
7403
|
-
})
|
|
7404
|
-
);
|
|
7405
|
-
if (choice === "cancel") proceedCustom = false;
|
|
7406
|
-
else if (choice === "migrate") edgeMigrate = true;
|
|
7407
|
-
else edgeTakeover = true;
|
|
7408
|
-
}
|
|
7419
|
+
const edge = await promptLocalEdgeTakeover(port);
|
|
7420
|
+
const proceedCustom = edge.proceed;
|
|
7421
|
+
const edgeTakeover = edge.edgeTakeover;
|
|
7422
|
+
const edgeMigrate = edge.edgeMigrate;
|
|
7409
7423
|
if (!proceedCustom) {
|
|
7410
7424
|
log5.warn(
|
|
7411
7425
|
"Left the existing proxy on 80/443 running. Registering Openship without managed HTTPS \u2014 front it with your proxy, or re-run setup to take over."
|
|
@@ -7460,13 +7474,16 @@ async function runWizard() {
|
|
|
7460
7474
|
function storedPorts2() {
|
|
7461
7475
|
const p = join19(OS_DIR, "ports.json");
|
|
7462
7476
|
try {
|
|
7463
|
-
return existsSync18(p) ? JSON.parse(
|
|
7477
|
+
return existsSync18(p) ? JSON.parse(readFileSync16(p, "utf8")) : {};
|
|
7464
7478
|
} catch {
|
|
7465
7479
|
return {};
|
|
7466
7480
|
}
|
|
7467
7481
|
}
|
|
7468
7482
|
async function runControl() {
|
|
7469
7483
|
const svc = serviceStatus();
|
|
7484
|
+
const isCompose = readInstallMethod() === "compose";
|
|
7485
|
+
const running = isCompose ? composeRunning() : svc.running;
|
|
7486
|
+
const managerLabel = isCompose ? "docker compose" : svc.kind === "unsupported" ? "none" : svc.kind;
|
|
7470
7487
|
const ports = storedPorts2();
|
|
7471
7488
|
const apiPort2 = String(ports.api ?? 4e3);
|
|
7472
7489
|
const dashUrl = `http://localhost:${ports.dashboard ?? 3001}`;
|
|
@@ -7475,10 +7492,10 @@ async function runControl() {
|
|
|
7475
7492
|
intro3(`${chalk20.bgCyan(chalk20.black(" Openship "))}${chalk20.dim(" control")}`);
|
|
7476
7493
|
note3(
|
|
7477
7494
|
`${chalk20.dim("URL".padEnd(11))}${chalk20.bold(primaryUrl)}
|
|
7478
|
-
${chalk20.dim("Service".padEnd(11))}${
|
|
7495
|
+
${chalk20.dim("Service".padEnd(11))}${running ? chalk20.green("running") : chalk20.yellow("stopped")}
|
|
7479
7496
|
${chalk20.dim("Dashboard".padEnd(11))}${dashUrl}
|
|
7480
7497
|
` + (ports.api ? `${chalk20.dim("API".padEnd(11))}http://localhost:${ports.api}
|
|
7481
|
-
` : "") + `${chalk20.dim("Manager".padEnd(11))}${
|
|
7498
|
+
` : "") + `${chalk20.dim("Manager".padEnd(11))}${managerLabel}`,
|
|
7482
7499
|
"Openship is already set up"
|
|
7483
7500
|
);
|
|
7484
7501
|
const corrupted = looksCorrupted();
|
|
@@ -7491,7 +7508,7 @@ ${chalk20.dim("Dashboard".padEnd(11))}${dashUrl}
|
|
|
7491
7508
|
options: [
|
|
7492
7509
|
...corrupted ? [{ value: "repair", label: "Repair database", hint: "backup \u2192 heal \u2192 verify" }] : [],
|
|
7493
7510
|
{ value: "open", label: "Open the dashboard" },
|
|
7494
|
-
|
|
7511
|
+
running ? { value: "restart", label: "Restart the service" } : { value: "start", label: "Start the service" },
|
|
7495
7512
|
{ value: "stop", label: "Stop the service", hint: "won't restart on boot" },
|
|
7496
7513
|
...corrupted ? [] : [{ value: "repair", label: "Repair database", hint: "backup \u2192 heal a corrupt DB" }],
|
|
7497
7514
|
{ value: "reset", label: "Reset admin password", hint: "sets a local email + password login" },
|
|
@@ -7511,15 +7528,31 @@ ${chalk20.dim("Dashboard".padEnd(11))}${dashUrl}
|
|
|
7511
7528
|
});
|
|
7512
7529
|
outro3(chalk20.dim(`Opening ${primaryUrl}`));
|
|
7513
7530
|
return;
|
|
7514
|
-
case "start":
|
|
7531
|
+
case "start": {
|
|
7532
|
+
if (isCompose) {
|
|
7533
|
+
const ok3 = composeStart();
|
|
7534
|
+
outro3(ok3 ? chalk20.green("Started.") : chalk20.yellow("Couldn't start the stack \u2014 run `openship up` to see the error."));
|
|
7535
|
+
return;
|
|
7536
|
+
}
|
|
7515
7537
|
await startService({});
|
|
7516
7538
|
return;
|
|
7539
|
+
}
|
|
7517
7540
|
case "restart": {
|
|
7541
|
+
if (isCompose) {
|
|
7542
|
+
const ok3 = composeRestart();
|
|
7543
|
+
outro3(ok3 ? chalk20.green("Restarted.") : chalk20.yellow("Couldn't restart the stack."));
|
|
7544
|
+
return;
|
|
7545
|
+
}
|
|
7518
7546
|
const r = restart();
|
|
7519
7547
|
outro3(r.restarted ? chalk20.green("Restarted.") : chalk20.yellow(r.detail));
|
|
7520
7548
|
return;
|
|
7521
7549
|
}
|
|
7522
7550
|
case "stop": {
|
|
7551
|
+
if (isCompose) {
|
|
7552
|
+
const ok3 = composeDown();
|
|
7553
|
+
outro3(ok3 ? chalk20.green("Stopped. Won't restart on boot.") : chalk20.yellow("Couldn't stop the stack."));
|
|
7554
|
+
return;
|
|
7555
|
+
}
|
|
7523
7556
|
const r = stop();
|
|
7524
7557
|
outro3(chalk20.green(`Stopped. ${chalk20.dim(r.detail)}`));
|
|
7525
7558
|
return;
|
|
@@ -7544,10 +7577,11 @@ ${chalk20.dim("Dashboard".padEnd(11))}${dashUrl}
|
|
|
7544
7577
|
|
|
7545
7578
|
// src/index.ts
|
|
7546
7579
|
var program = new Command28();
|
|
7547
|
-
program.name("openship").description("Openship CLI \u2014 install, run, and manage Openship from your terminal").version("0.4.
|
|
7580
|
+
program.name("openship").description("Openship CLI \u2014 install, run, and manage Openship from your terminal").version("0.4.7").option("--json", "Machine-readable JSON output (stdout data only)").hook("preAction", (thisCommand) => {
|
|
7548
7581
|
if (thisCommand.opts().json) setJsonMode(true);
|
|
7549
7582
|
}).action(async () => {
|
|
7550
|
-
|
|
7583
|
+
const installed = serviceStatus().installed || readInstallMethod() === "compose";
|
|
7584
|
+
if (installed && !isSetupInProgress()) await runControl();
|
|
7551
7585
|
else await runWizard();
|
|
7552
7586
|
});
|
|
7553
7587
|
program.addCommand(upCommand);
|