Source Discovery
Source discovery is an allowlisted read-only operation. HostShift treats the source as an observation endpoint and never writes to it.
Fact Execution
Section titled “Fact Execution”hostshift discover runs each fact through the source command guard. Required facts must succeed. Optional facts can fail and still be reported in the JSON output.
hostshift discover --source old-server --name migration --profile migration.profile.yaml --jsonRequired Facts
Section titled “Required Facts”Required facts currently include:
osRelease:cat /etc/os-releasearchitecture:uname -mhostname:hostnamedisk:df -Pkmemory:cat /proc/meminfopackages:dpkg-query -W -f=${binary:Package}\t${Version}\nmounts:findmnt --json --realusers:getent passwdgroups:getent group
If any required fact fails, discovery fails instead of generating a misleading profile.
Optional Facts
Section titled “Optional Facts”Optional facts provide workload hints:
enabledServicesrunningServiceslistenersufwStatusnftRulesetsshdEffectiveConfigsshdConfigmysqlServerConfigmysqlDatabasespostgresDatabasesnginxConfigDumpapacheConfigDumpcaddyConfigPathsphpConfigPathssupervisorConfigPathsfail2banConfigPathsmemcachedConfigPathsrabbitmqConfigPathslogrotateConfigPathsletsEncryptFilescroncustomSystemdUnitsdockerVersiondockerComposeProjectsdockerContainersdockerNetworks
Optional failures are visible in output and should be reviewed before migration.
Generated Profile
Section titled “Generated Profile”Discovery writes a profile with:
schemaVersion: 2source.sshset to the discovered aliassourcePolicy: strict-read-onlyapproved: falseplatforms.sourcepopulated from/etc/os-releasewhen available- safe workload candidates derived from reviewed facts
- empty checks
Generated workload candidates currently include:
- Docker Compose projects from
docker compose ls --format json - matching Compose working directories as
file-setworkloads - standalone Docker containers from
docker ps --format /etc/nginxwhennginx -Tsucceeds/etc/apache2whenapache2ctl -Ssucceeds- an
apache-vhostactivation candidate when Apache config is discovered - Caddy configuration files under
/etc/caddywhen Caddy config files are discovered caddyreload candidates when/etc/caddyfiles,caddy.service, or thecaddypackage are discovered- PHP configuration files under
/etc/phpwhen PHP-FPM config files are discovered php-fpmreload candidates whenphp*-fpm.serviceorphp*-fpmpackages are discovered- Supervisor configuration files under
/etc/supervisorwhen Supervisor config files are discovered supervisorupdate candidates when/etc/supervisorfiles,supervisor.service, or thesupervisorpackage are discovered- Fail2ban configuration files under
/etc/fail2banwhen Fail2ban config files are discovered fail2banreload candidates when/etc/fail2banfiles,fail2ban.service, or thefail2banpackage are discovered- Memcached configuration files under
/etc/memcached.confand/etc/memcachedwhen Memcached config files are discovered memcachedrestart candidates when/etc/memcached.conf,/etc/memcachedfiles,memcached.service, or thememcachedpackage are discovered- RabbitMQ configuration files under
/etc/rabbitmqwhen RabbitMQ config files are discovered rabbitmqrestart candidates when/etc/rabbitmqfiles,rabbitmq-server.service, or therabbitmq-serverpackage are discovered- Let’s Encrypt state under
/etc/letsencryptwhen Certbot files are discovered certbotvalidation candidates when/etc/letsencryptfiles or thecertbotpackage are discovered- Logrotate configuration files under
/etc/logrotate.confand/etc/logrotate.dwhen Logrotate config files are discovered logrotatevalidation candidates when/etc/logrotate.conf,/etc/logrotate.dfiles, or thelogrotatepackage are discovered/etc/letsencryptwhen certificate files are discovered- cron files under
/etc/cron.d,/etc/cron.daily,/etc/cron.hourly,/etc/cron.monthly, and/etc/cron.weekly - a
crontarget reload candidate when cron files are discovered - custom systemd unit files under
/etc/systemd/system systemd-servicecutover candidates for discovered custom units that are enabledrediscandidates whenredis-serveris found through packages or systemd facts- non-system MySQL/MariaDB databases
- non-system PostgreSQL databases
HostShift does not generate systemd-service workloads from distribution service lists alone because it cannot safely distinguish application units from system units without operator review.
Redis candidates intentionally do not include a default export strategy. Operators must add either snapshotPath for an existing RDB file or replicaHost for a read-only replica stream before approval.
Docker named volumes are discovered with the read-only docker volume ls command. Each becomes a docker-volume workload without a default strategy, so apply remains blocked until the operator selects snapshot, disposable, database-backed, or external. HostShift does not inspect or archive volume contents during discovery.
RabbitMQ candidates preserve configuration only. Live queues and messages are not migrated by discovery-generated workloads.
Certbot candidates preserve existing Let’s Encrypt files only. DNS routing, ACME challenge behavior, and future renewal behavior must be reviewed separately.
Operators must still review the generated profile, fill in the target, add checks, remove unwanted candidates, add missing workload metadata such as password environment variable names, and set approved: true only after review.
Source Immutability
Section titled “Source Immutability”Discovery does not use:
sudo- package installation
- service management
- file writes
- snapshot creation
- maintenance mode
- firewall changes
The same source command guard also protects source-side sync streams.