This is the most recent iteration of the script:
❯ cat custom_rustup.sh
#!/bin/sh
# Customized rustup.sh for Termux on aarch64-unknown-linux-musl with specific fixes
# Exit immediately if a command exits with a non-zero status
set -e
# Enable debug mode: prints each command before executing
set -x
# ----- 1. Define the host triple for Termux -----
# Use the standard host triple
HOST_TRIPLE="aarch64-unknown-linux-musl"
# ----- 2. Set the Rustup update root -----
# Define the root URL for rustup updates
RUSTUP_UPDATE_ROOT="${RUSTUP_UPDATE_ROOT:-https://static.rust-lang.org/rustup}"
# ----- 3. Define the installer URL based on the host triple -----
INSTALLER_URL="${RUSTUP_UPDATE_ROOT}/dist/${HOST_TRIPLE}/rustup-init"
# ----- 4. Use Termux's temporary directory -----
# Ensure the temporary directory exists
TEMP_DIR="${TMPDIR:-$PREFIX/tmp}"
mkdir -p "$TEMP_DIR" || { echo "Failed to create temporary directory"; exit 1; }
# Create a temporary file for the installer
INSTALLER_FILE="$(mktemp "$TEMP_DIR/rustup-init.XXXXXX")" || { echo "Failed to create temporary file"; exit 1; }
# ----- 5. Logging Functions -----
# Function to log informational messages
log_info() {
echo "INFO: $1" >&2
}
# Function to log error messages
log_error() {
echo "ERROR: $1" >&2
}
# ----- 6. Download the installer using curl or wget with IPv4 enforcement -----
if command -v curl >/dev/null 2>&1; then
log_info "Using curl to download rustup-init script"
# Force IPv4 usage with -4 to avoid IPv6 DNS issues
curl -4 --proto '=https' --tlsv1.2 -v -sSf "$INSTALLER_URL" -o "$INSTALLER_FILE" || {
log_error "Failed to download rustup-init script using curl"
exit 1
}
elif command -v wget >/dev/null 2>&1; then
log_info "Using wget to download rustup-init script"
# Force IPv4 usage with --inet4-only to avoid IPv6 DNS issues
wget --inet4-only -v "$INSTALLER_URL" -O "$INSTALLER_FILE" || {
log_error "Failed to download rustup-init script using wget"
exit 1
}
else
log_error "Neither curl nor wget is installed. Please install one of them and retry."
exit 1
fi
# ----- 7. Make the installer executable -----
# Ensure the downloaded installer has execute permissions
chmod +x "$INSTALLER_FILE" || { log_error "Failed to make installer executable"; exit 1; }
# ----- 8. Ensure the HOME environment variable is set correctly -----
export HOME="/data/data/com.termux/files/home"
# Set essential environment variables
export USER=$(whoami)
export LOGNAME=$USER
# Verify that $HOME exists and is writable
if [ ! -d "$HOME" ] || [ ! -w "$HOME" ]; then
log_error "HOME directory '$HOME' does not exist or is not writable."
exit 1
fi
# ----- 9. Restore Original User Entry in /etc/passwd -----
# Ensure that /etc/passwd contains an entry for the current user
grep "^$USER:" /data/data/com.termux/files/usr/etc/passwd >/dev/null 2>&1 || {
log_info "Adding user entry for '$USER' to /data/data/com.termux/files/usr/etc/passwd"
echo "$USER:x:10819:10819:User:/data/data/com.termux/files/home:/data/data/com.termux/files/usr/bin/bash" >> /data/data/com.termux/files/usr/etc/passwd
}
# ----- 10. Debugging: Check if the installer now contains the host triple -----
log_info "DEBUG: Checking installer for host triple" # Use 'strings' to search within a binary
if ! strings "$INSTALLER_FILE" | grep -q "aarch64-unknown-linux-musl"; then log_info "The installer does not contain the standard host triple 'aarch64-unknown-linux-musl'. Proceeding with standard host triple."
fi
# ----- 11. Debugging: Attempt to manually resolve the URL within the script ----- log_info "Verifying DNS resolution for channel-rust-stable.toml.sha256"
# Force IPv4 with -4 in curl to ensure consistent networking
curl -4 --proto '=https' --tlsv1.2 -v -sSf "https://static.rust-lang.org/dist/channel-rust-stable.toml.sha256" -o /dev/null || {
log_error "DNS resolution or connectivity issue detected when accessing channel-rust-stable.toml.sha256"
exit 1
}
log_info "DNS resolution successful for channel-rust-stable.toml.sha256"
# ----- 12. Set environment variable for verbose rustup logging ----- export RUSTUP_LOG=trace
# ----- 13. Logging the installer parameters for clarity -----
log_info "Running rustup installer with the following parameters:"
log_info "--default-toolchain 1.67.1"
log_info "--default-host aarch64-unknown-linux-musl"
log_info "--profile default"
log_info "--no-modify-path"
log_info "-y"
# ----- 14. Execute the installer ----- # Run the rustup-init installer with specified parameters
"$INSTALLER_FILE" \
--default-toolchain 1.67.1 \
--default-host "$HOST_TRIPLE" \
--profile default \
--no-modify-path \
-y || {
log_error "Rustup installation failed. Check the logs above for details."
exit 1
}
# ----- 15. Clean up the installer file -----
# Remove the temporary installer script
rm "$INSTALLER_FILE" || {
log_error "Failed to remove installer file"
exit 1
}
# ----- 16. Source Cargo's environment to update PATH ----- # Update the current shell's PATH to include Cargo's bin directory
if [ -f "$HOME/.cargo/env" ]; then
. "$HOME/.cargo/env" || {
log_error "Failed to source Cargo's environment script"
exit 1 }
fi
# ----- 17. Completion Message -----
log_info "Rust installation completed successfully." log_info "To configure your current shell, run:"
log_info ". \"$HOME/.cargo/env\""
# Exit the script successfully
exit 0
This is the execution log:
❯ ./custom_rustup.sh
+ HOST_TRIPLE=aarch64-unknown-linux-musl
+ RUSTUP_UPDATE_ROOT=https://static.rust-lang.org/rustup
+ INSTALLER_URL=https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-musl/rustup-init
+ TEMP_DIR=/data/data/com.termux/files/usr/tmp
+ mkdir -p /data/data/com.termux/files/usr/tmp
+ mktemp /data/data/com.termux/files/usr/tmp/rustup-init.XXXXXX
+ INSTALLER_FILE=/data/data/com.termux/files/usr/tmp/rustup-init.0PxjCo
+ command -v curl
+ log_info Using curl to download rustup-init script
+ echo INFO: Using curl to download rustup-init script
INFO: Using curl to download rustup-init script
+ curl -4 --proto =https --tlsv1.2 -v -sSf https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-musl/rustup-init -o /data/data/com.termux/files/usr/tmp/rustup-init.0PxjCo * Host static.rust-lang.org:443 was resolved.
* IPv6: (none)
* IPv4: 99.86.212.77, 99.86.212.120, 99.86.212.91, 99.86.212.62
* Trying 99.86.212.77:443...
* ALPN: curl offers h2,http/1.1
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* CAfile: /data/data/com.termux/files/usr/etc/tls/cert.pem
* CApath: /data/data/com.termux/files/usr/etc/tls/certs
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [122 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [19 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [5016 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [264 bytes data] * TLSv1.3 (IN), TLS handshake, Finished (20):
{ [36 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20): } [36 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
* subject: CN=doc.rust-lang.org
* start date: May 7 00:00:00 2024 GMT
* expire date: Jun 5 23:59:59 2025 GMT * subjectAltName: host "static.rust-lang.org" matched cert's "static.rust-lang.org"
* issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M03
* SSL certificate verify ok.
* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Connected to static.rust-lang.org (99.86.212.77) port 443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-musl/rustup-init
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: static.rust-lang.org]
* [HTTP/2] [1] [:path: /rustup/dist/aarch64-unknown-linux-musl/rustup-init]
* [HTTP/2] [1] [user-agent: curl/8.11.0]
* [HTTP/2] [1] [accept: */*]
} [5 bytes data]
> GET /rustup/dist/aarch64-unknown-linux-musl/rustup-init HTTP/2
> Host: static.rust-lang.org > User-Agent: curl/8.11.0
> Accept: */* >
* Request completely sent off
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): { [124 bytes data]
< HTTP/2 200 < content-type: binary/octet-stream
< content-length: 15187976
< last-modified: Mon, 06 May 2024 12:11:29 GMT
< x-amz-server-side-encryption: AES256
< x-amz-version-id: _rMHSsUuze2EbOObl9D3baiwNomxXlR5
< accept-ranges: bytes
< server: AmazonS3
< date: Sun, 08 Dec 2024 19:50:40 GMT
< etag: "a9b9c05022002a88de60df35af67f2d1-2"
< vary: Accept-Encoding
< x-cache: RefreshHit from cloudfront
< via: 1.1 00a314d3067bbe664b5e4545893a12d8.cloudfront.net (CloudFront)
< x-amz-cf-pop: MEL51-P1
< x-amz-cf-id: 9PsDpvItGepThHfKvQSxI5J8TMYPmtwBfN8RZfldkB2EtI7sw4ZbFA==
<
{ [8192 bytes data]
* Connection #0 to host static.rust-lang.org left intact
+ chmod +x /data/data/com.termux/files/usr/tmp/rustup-init.0PxjCo
+ export HOME=/data/data/com.termux/files/home
+ whoami + export USER=u0_a819
+ export LOGNAME=u0_a819
+ [ ! -d /data/data/com.termux/files/home ]
+ [ ! -w /data/data/com.termux/files/home ]
+ grep ^u0_a819: /data/data/com.termux/files/usr/etc/passwd
+ log_info DEBUG: Checking installer for host triple
+ echo INFO: DEBUG: Checking installer for host triple
INFO: DEBUG: Checking installer for host triple
+ strings /data/data/com.termux/files/usr/tmp/rustup-init.0PxjCo
+ grep -q aarch64-unknown-linux-gnu
+ log_info Verifying DNS resolution for channel-rust-stable.toml.sha256
+ echo INFO: Verifying DNS resolution for channel-rust-stable.toml.sha256
INFO: Verifying DNS resolution for channel-rust-stable.toml.sha256 + curl -4 --proto =https --tlsv1.2 -v -sSf https://static.rust-lang.org/dist/channel-rust-stable.toml.sha256 -o /dev/null
* Host static.rust-lang.org:443 was resolved.
* IPv6: (none)
* IPv4: 99.86.212.77, 99.86.212.120, 99.86.212.91, 99.86.212.62
* Trying 99.86.212.77:443...
* ALPN: curl offers h2,http/1.1
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* CAfile: /data/data/com.termux/files/usr/etc/tls/cert.pem
* CApath: /data/data/com.termux/files/usr/etc/tls/certs
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [122 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): { [19 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11): { [5016 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [264 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [36 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [36 bytes data] * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
* subject: CN=doc.rust-lang.org
* start date: May 7 00:00:00 2024 GMT
* expire date: Jun 5 23:59:59 2025 GMT
* subjectAltName: host "static.rust-lang.org" matched cert's "static.rust-lang.org"
* issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M03
* SSL certificate verify ok.
* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption * Connected to static.rust-lang.org (99.86.212.77) port 443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://static.rust-lang.org/dist/channel-rust-stable.toml.sha256
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: static.rust-lang.org]
* [HTTP/2] [1] [:path: /dist/channel-rust-stable.toml.sha256]
* [HTTP/2] [1] [user-agent: curl/8.11.0]
* [HTTP/2] [1] [accept: */*]
} [5 bytes data]
> GET /dist/channel-rust-stable.toml.sha256 HTTP/2
> Host: static.rust-lang.org
> User-Agent: curl/8.11.0
> Accept: */*
>
* Request completely sent off
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [124 bytes data]
< HTTP/2 200
< content-type: binary/octet-stream < content-length: 91
< date: Sun, 08 Dec 2024 02:13:04 GMT
< last-modified: Thu, 28 Nov 2024 13:58:25 GMT
< etag: "857c2bb99867dc533f78c991b02f3d64"
< x-amz-storage-class: INTELLIGENT_TIERING
< x-amz-server-side-encryption: AES256 < x-amz-version-id: N4D2qz7uwqNzmmjEHX9iD6KHGUX5SMB2 < accept-ranges: bytes < server: AmazonS3
< x-cache: Hit from cloudfront
< via: 1.1 d830b6c97f08553c0cdff2ca40914622.cloudfront.net (CloudFront)
< x-amz-cf-pop: MEL51-P1
< x-amz-cf-id: 0lgm5DBhVFkKlDg99gy4Q8Ri2zfn8RRofs3TEisnv96rtRufqPmhPg==
< age: 63458 <
{ [91 bytes data]
* Connection #0 to host static.rust-lang.org left intact
+ log_info DNS resolution successful for channel-rust-stable.toml.sha256
+ echo INFO: DNS resolution successful for channel-rust-stable.toml.sha256
INFO: DNS resolution successful for channel-rust-stable.toml.sha256 + export RUSTUP_LOG=trace
+ log_info Running rustup installer with the following parameters:
+ echo INFO: Running rustup installer with the following parameters: INFO: Running rustup installer with the following parameters:
+ log_info --default-toolchain 1.67.1 + echo INFO: --default-toolchain 1.67.1
INFO: --default-toolchain 1.67.1 + log_info --default-host aarch64-unknown-linux-musl
+ echo INFO: --default-host aarch64-unknown-linux-musl
INFO: --default-host aarch64-unknown-linux-musl + log_info --profile default
+ echo INFO: --profile default INFO: --profile default
+ log_info --no-modify-path
+ echo INFO: --no-modify-path
INFO: --no-modify-path
+ log_info -y
+ echo INFO: -y
INFO: -y
+ /data/data/com.termux/files/usr/tmp/rustup-init.0PxjCo --default-toolchain 1.67.1 --default-host aarch64-unknown-linux-musl --profile default --no-modify-path -y
./custom_rustup.sh: 113: /data/data/com.termux/files/usr/tmp/rustup-init.0PxjCo: not found + log_error Rustup installation failed. Check the logs above for details.
+ echo ERROR: Rustup installation failed. Check the logs above for details.
ERROR: Rustup installation failed. Check the logs above for details.
+ exit 1
There may be some way to marry the script with what I did with the manually downloaded rustup installation binary and the manually downloaded channel file, but my skills are not yet that keen.
If anyone is interested, these are the two code snippets I used to manually acquire the assets:
curl -4 --proto '=https' --tlsv1.2 -sSf https://static.rust-lang.org/rustup/dist/aarch64-unknown-linux-musl/rustup-init -o ~/rustup-init-musl
chmod +x ~/rustup-init-musl
And:
mkdir -p ~/.rustup/tmp
curl -4 --proto '=https' --tlsv1.2 -sSf https://static.rust-lang.org/dist/channel-rust-1.67.1.toml.sha256 -o ~/.rustup/tmp/channel-rust-1.67.1.toml.sha256
All this smoke and fire, but no cigar.