Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bbe301b38 | ||
|
|
d725d633cd |
-256
@@ -1,256 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
|
|
||||||
REM Claude Code Windows CMD Bootstrap Script
|
|
||||||
REM Installs Claude Code for environments where PowerShell is not available
|
|
||||||
|
|
||||||
REM Parse command line argument
|
|
||||||
set "TARGET=%~1"
|
|
||||||
if "!TARGET!"=="" set "TARGET=latest"
|
|
||||||
|
|
||||||
REM Validate target parameter
|
|
||||||
if /i "!TARGET!"=="stable" goto :target_valid
|
|
||||||
if /i "!TARGET!"=="latest" goto :target_valid
|
|
||||||
echo !TARGET! | findstr /r "^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*" >nul
|
|
||||||
if !ERRORLEVEL! equ 0 goto :target_valid
|
|
||||||
|
|
||||||
echo Usage: %0 [stable^|latest^|VERSION] >&2
|
|
||||||
echo Example: %0 1.0.58 >&2
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:target_valid
|
|
||||||
|
|
||||||
REM Check for 64-bit Windows
|
|
||||||
if /i "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto :arch_valid
|
|
||||||
if /i "%PROCESSOR_ARCHITECTURE%"=="ARM64" goto :arch_valid
|
|
||||||
if /i "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto :arch_valid
|
|
||||||
if /i "%PROCESSOR_ARCHITEW6432%"=="ARM64" goto :arch_valid
|
|
||||||
|
|
||||||
echo Claude Code does not support 32-bit Windows. Please use a 64-bit version of Windows. >&2
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:arch_valid
|
|
||||||
|
|
||||||
REM Set constants
|
|
||||||
set "DOWNLOAD_BASE_URL=https://downloads.claude.ai/claude-code-releases"
|
|
||||||
set "DOWNLOAD_DIR=%USERPROFILE%\.claude\downloads"
|
|
||||||
REM Use native ARM64 binary on ARM64 Windows, x64 otherwise
|
|
||||||
if /i "%PROCESSOR_ARCHITECTURE%"=="ARM64" (
|
|
||||||
set "PLATFORM=win32-arm64"
|
|
||||||
) else (
|
|
||||||
set "PLATFORM=win32-x64"
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Create download directory
|
|
||||||
if not exist "!DOWNLOAD_DIR!" mkdir "!DOWNLOAD_DIR!"
|
|
||||||
|
|
||||||
REM Check for curl availability
|
|
||||||
curl --version >nul 2>&1
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
echo curl is required but not available. Please install curl or use PowerShell installer. >&2
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Always download latest version (which has the most up-to-date installer)
|
|
||||||
call :download_file "!DOWNLOAD_BASE_URL!/latest" "!DOWNLOAD_DIR!\latest"
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
echo Failed to get latest version >&2
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Reject non-version content (e.g. an HTML error page) before it reaches the manifest URL
|
|
||||||
findstr /r "^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*" "!DOWNLOAD_DIR!\latest" >nul
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
del "!DOWNLOAD_DIR!\latest"
|
|
||||||
echo Failed to get a valid version from downloads.claude.ai - got unexpected content. >&2
|
|
||||||
echo This can happen if the download service is unreachable or not available in your region - see https://www.anthropic.com/supported-countries >&2
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Read version from file
|
|
||||||
set /p VERSION=<"!DOWNLOAD_DIR!\latest"
|
|
||||||
del "!DOWNLOAD_DIR!\latest"
|
|
||||||
|
|
||||||
REM Download manifest
|
|
||||||
call :download_file "!DOWNLOAD_BASE_URL!/!VERSION!/manifest.json" "!DOWNLOAD_DIR!\manifest.json"
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
echo Failed to get manifest >&2
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Extract checksum from manifest
|
|
||||||
call :parse_manifest "!DOWNLOAD_DIR!\manifest.json" "!PLATFORM!"
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
echo Platform !PLATFORM! not found in manifest >&2
|
|
||||||
del "!DOWNLOAD_DIR!\manifest.json" 2>nul
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
del "!DOWNLOAD_DIR!\manifest.json"
|
|
||||||
|
|
||||||
REM Download binary
|
|
||||||
set "BINARY_PATH=!DOWNLOAD_DIR!\claude-!VERSION!-!PLATFORM!.exe"
|
|
||||||
call :download_file "!DOWNLOAD_BASE_URL!/!VERSION!/!PLATFORM!/claude.exe" "!BINARY_PATH!"
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
echo Failed to download binary >&2
|
|
||||||
if exist "!BINARY_PATH!" del "!BINARY_PATH!"
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Verify checksum
|
|
||||||
call :verify_checksum "!BINARY_PATH!" "!EXPECTED_CHECKSUM!"
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
echo Checksum verification failed >&2
|
|
||||||
del "!BINARY_PATH!"
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Run claude install to set up launcher and shell integration
|
|
||||||
echo Setting up Claude Code...
|
|
||||||
"!BINARY_PATH!" install "!TARGET!"
|
|
||||||
set "INSTALL_RESULT=!ERRORLEVEL!"
|
|
||||||
|
|
||||||
REM Clean up downloaded file
|
|
||||||
REM Wait a moment for any file handles to be released
|
|
||||||
timeout /t 1 /nobreak >nul 2>&1
|
|
||||||
del /f "!BINARY_PATH!" >nul 2>&1
|
|
||||||
if exist "!BINARY_PATH!" (
|
|
||||||
echo Warning: Could not remove temporary file: !BINARY_PATH!
|
|
||||||
)
|
|
||||||
|
|
||||||
if !INSTALL_RESULT! neq 0 (
|
|
||||||
echo Installation failed >&2
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Installation complete^^!
|
|
||||||
echo.
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
REM ============================================================================
|
|
||||||
REM SUBROUTINES
|
|
||||||
REM ============================================================================
|
|
||||||
|
|
||||||
:download_file
|
|
||||||
REM Downloads a file using curl
|
|
||||||
REM Args: %1=URL, %2=OutputPath
|
|
||||||
set "URL=%~1"
|
|
||||||
set "OUTPUT=%~2"
|
|
||||||
|
|
||||||
REM Capture stderr so a certificate-revocation failure can be detected below
|
|
||||||
curl -fsSL "!URL!" -o "!OUTPUT!" 2>"!OUTPUT!.stderr"
|
|
||||||
set "CURL_RESULT=!ERRORLEVEL!"
|
|
||||||
if !CURL_RESULT! equ 0 goto :download_file_done
|
|
||||||
|
|
||||||
REM Some networks (commonly corporate ones) block the endpoints Windows uses
|
|
||||||
REM to check whether a TLS certificate has been revoked. curl's schannel
|
|
||||||
REM backend then fails with CRYPT_E_NO_REVOCATION_CHECK (0x80092012) or
|
|
||||||
REM CRYPT_E_REVOCATION_OFFLINE (0x80092013). Retry once with best-effort
|
|
||||||
REM revocation checking - the soft-fail behavior browsers use: an unreachable
|
|
||||||
REM revocation server is tolerated, but a certificate that is known to be
|
|
||||||
REM revoked is still rejected.
|
|
||||||
findstr /i /c:"0x80092012" /c:"0x80092013" "!OUTPUT!.stderr" >nul
|
|
||||||
if !ERRORLEVEL! neq 0 (
|
|
||||||
type "!OUTPUT!.stderr" >&2
|
|
||||||
goto :download_file_done
|
|
||||||
)
|
|
||||||
|
|
||||||
echo This network appears to block certificate revocation checks. Retrying the download with best-effort revocation checking... >&2
|
|
||||||
curl -fsSL --ssl-revoke-best-effort "!URL!" -o "!OUTPUT!"
|
|
||||||
set "CURL_RESULT=!ERRORLEVEL!"
|
|
||||||
REM If the retry also failed, re-emit the original error so the actionable
|
|
||||||
REM schannel diagnostic is not lost
|
|
||||||
if !CURL_RESULT! neq 0 type "!OUTPUT!.stderr" >&2
|
|
||||||
|
|
||||||
:download_file_done
|
|
||||||
del "!OUTPUT!.stderr" >nul 2>&1
|
|
||||||
exit /b !CURL_RESULT!
|
|
||||||
|
|
||||||
:parse_manifest
|
|
||||||
REM Parse JSON manifest to extract checksum for platform
|
|
||||||
REM Args: %1=ManifestPath, %2=Platform
|
|
||||||
set "MANIFEST_PATH=%~1"
|
|
||||||
set "PLATFORM_NAME=%~2"
|
|
||||||
set "EXPECTED_CHECKSUM="
|
|
||||||
|
|
||||||
REM Use findstr to find platform section, then look for checksum
|
|
||||||
set "FOUND_PLATFORM="
|
|
||||||
set "IN_PLATFORM_SECTION="
|
|
||||||
|
|
||||||
REM Read the manifest line by line
|
|
||||||
for /f "usebackq tokens=*" %%i in ("!MANIFEST_PATH!") do (
|
|
||||||
set "LINE=%%i"
|
|
||||||
|
|
||||||
REM Check if this line contains our platform
|
|
||||||
echo !LINE! | findstr /c:"\"%PLATFORM_NAME%\":" >nul
|
|
||||||
if !ERRORLEVEL! equ 0 (
|
|
||||||
set "IN_PLATFORM_SECTION=1"
|
|
||||||
)
|
|
||||||
|
|
||||||
REM If we're in the platform section, look for checksum
|
|
||||||
if defined IN_PLATFORM_SECTION (
|
|
||||||
echo !LINE! | findstr /c:"\"checksum\":" >nul
|
|
||||||
if !ERRORLEVEL! equ 0 (
|
|
||||||
REM Extract checksum value
|
|
||||||
for /f "tokens=2 delims=:" %%j in ("!LINE!") do (
|
|
||||||
set "CHECKSUM_PART=%%j"
|
|
||||||
REM Remove quotes, whitespace, and comma
|
|
||||||
set "CHECKSUM_PART=!CHECKSUM_PART: =!"
|
|
||||||
set "CHECKSUM_PART=!CHECKSUM_PART:"=!"
|
|
||||||
set "CHECKSUM_PART=!CHECKSUM_PART:,=!"
|
|
||||||
|
|
||||||
REM Check if it looks like a SHA256 (64 hex chars)
|
|
||||||
if not "!CHECKSUM_PART!"=="" (
|
|
||||||
call :check_length "!CHECKSUM_PART!" 64
|
|
||||||
if !ERRORLEVEL! equ 0 (
|
|
||||||
set "EXPECTED_CHECKSUM=!CHECKSUM_PART!"
|
|
||||||
exit /b 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Check if we've left the platform section (closing brace)
|
|
||||||
echo !LINE! | findstr /c:"}" >nul
|
|
||||||
if !ERRORLEVEL! equ 0 set "IN_PLATFORM_SECTION="
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if "!EXPECTED_CHECKSUM!"=="" exit /b 1
|
|
||||||
exit /b 0
|
|
||||||
|
|
||||||
:check_length
|
|
||||||
REM Check if string length equals expected length
|
|
||||||
REM Args: %1=String, %2=ExpectedLength
|
|
||||||
set "STR=%~1"
|
|
||||||
set "EXPECTED_LEN=%~2"
|
|
||||||
set "LEN=0"
|
|
||||||
:count_loop
|
|
||||||
if "!STR:~%LEN%,1!"=="" goto :count_done
|
|
||||||
set /a LEN+=1
|
|
||||||
goto :count_loop
|
|
||||||
:count_done
|
|
||||||
if %LEN%==%EXPECTED_LEN% exit /b 0
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:verify_checksum
|
|
||||||
REM Verify file checksum using certutil
|
|
||||||
REM Args: %1=FilePath, %2=ExpectedChecksum
|
|
||||||
set "FILE_PATH=%~1"
|
|
||||||
set "EXPECTED=%~2"
|
|
||||||
|
|
||||||
for /f "skip=1 tokens=*" %%i in ('certutil -hashfile "!FILE_PATH!" SHA256') do (
|
|
||||||
set "ACTUAL=%%i"
|
|
||||||
set "ACTUAL=!ACTUAL: =!"
|
|
||||||
if "!ACTUAL!"=="CertUtil:Thecommandcompletedsuccessfully." goto :verify_done
|
|
||||||
if "!ACTUAL!" neq "" (
|
|
||||||
if /i "!ACTUAL!"=="!EXPECTED!" (
|
|
||||||
exit /b 0
|
|
||||||
) else (
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
:verify_done
|
|
||||||
exit /b 1
|
|
||||||
+44
-6
@@ -24,6 +24,48 @@ for _ in $(seq 1 30); do
|
|||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Installe en 3 étapes séparées (partition -> swap sur le disque cible ->
|
||||||
|
# vrai build) au lieu d'un seul `disko-install`. Raison : disko-install
|
||||||
|
# fait tout d'un coup dans le tmpfs RAM de l'environnement live, qui sature
|
||||||
|
# sur les PC à peu de RAM (4 Go) avant même de toucher le disque cible.
|
||||||
|
# Un swapfile posé sur /mnt (une fois partitionné) donne accès aux ~200 Go
|
||||||
|
# du disque comme mémoire virtuelle pendant la vraie construction — méthode
|
||||||
|
# documentée officiellement pour les machines à RAM limitée, voir
|
||||||
|
# wiki.nixos.org/wiki/Swap et le manuel NixOS (section installation).
|
||||||
|
#
|
||||||
|
# Point non confirmé à 100% : que `disko` (seul, pas `disko-install`)
|
||||||
|
# accepte le même `--disk main <device>` que `disko-install`. La doc de
|
||||||
|
# référence de disko ne montre que `--argstr`, mais disko-install n'étant
|
||||||
|
# qu'un wrapper autour de disko, c'est très probable que ça marche pareil.
|
||||||
|
# Si la commande le refuse, l'erreur sera explicite.
|
||||||
|
do_install() {
|
||||||
|
local flake_url="$1"
|
||||||
|
local attr="$2"
|
||||||
|
|
||||||
|
echo "Partitionnement de $DEVICE..."
|
||||||
|
nix run --no-write-lock-file --refresh 'github:nix-community/disko' -- \
|
||||||
|
--mode destroy,format,mount \
|
||||||
|
--flake "${flake_url}#${attr}" \
|
||||||
|
--disk main "$DEVICE"
|
||||||
|
|
||||||
|
echo "Swap temporaire sur le disque cible (RAM limitée sur certains PC du parc)..."
|
||||||
|
dd if=/dev/zero of=/mnt/.install-swapfile bs=1M count=4096 status=none
|
||||||
|
chmod 600 /mnt/.install-swapfile
|
||||||
|
mkswap /mnt/.install-swapfile
|
||||||
|
swapon /mnt/.install-swapfile
|
||||||
|
|
||||||
|
echo "Construction et installation du système (peut prendre plusieurs minutes)..."
|
||||||
|
# --no-channel-copy, --no-root-passwd : confirmés dans le man nixos-install
|
||||||
|
# (mankier.com/8/nixos-install, miroir du manuel officiel). Le mot de
|
||||||
|
# passe root est de toute façon déjà déclaré (initialPassword) dans la
|
||||||
|
# config cible, --no-root-passwd évite juste tout risque de prompt
|
||||||
|
# interactif qui bloquerait un install non surveillé.
|
||||||
|
nixos-install --root /mnt --flake "${flake_url}#${attr}" --no-channel-copy --no-root-passwd
|
||||||
|
|
||||||
|
swapoff /mnt/.install-swapfile
|
||||||
|
rm -f /mnt/.install-swapfile
|
||||||
|
}
|
||||||
|
|
||||||
echo "=== Installeur Nixos_Fleet ==="
|
echo "=== Installeur Nixos_Fleet ==="
|
||||||
echo "1) PC de la flotte (générique)"
|
echo "1) PC de la flotte (générique)"
|
||||||
echo "2) Poste utilisateur nommé"
|
echo "2) Poste utilisateur nommé"
|
||||||
@@ -59,9 +101,7 @@ case "$CHOICE" in
|
|||||||
# --- Branche flotte : rien d'autre à saisir -----------------------
|
# --- Branche flotte : rien d'autre à saisir -----------------------
|
||||||
echo
|
echo
|
||||||
echo "Installation du profil générique 'usagers' sur $DEVICE..."
|
echo "Installation du profil générique 'usagers' sur $DEVICE..."
|
||||||
nix run --no-write-lock-file --refresh 'github:nix-community/disko#disko-install' -- --write-efi-boot-entries \
|
do_install "$FLEET_REPO" "usagers"
|
||||||
--flake "${FLEET_REPO}#usagers" \
|
|
||||||
--disk main "$DEVICE"
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
2)
|
2)
|
||||||
@@ -94,9 +134,7 @@ case "$CHOICE" in
|
|||||||
if [[ "$ATTR" == *-luks ]]; then
|
if [[ "$ATTR" == *-luks ]]; then
|
||||||
echo "Disque chiffré : disko va demander une passphrase LUKS pendant le partitionnement."
|
echo "Disque chiffré : disko va demander une passphrase LUKS pendant le partitionnement."
|
||||||
fi
|
fi
|
||||||
nix run --no-write-lock-file --refresh 'github:nix-community/disko#disko-install' -- --write-efi-boot-entries \
|
do_install "$AUTHED_URL" "$ATTR"
|
||||||
--flake "${AUTHED_URL}#${ATTR}" \
|
|
||||||
--disk main "$DEVICE"
|
|
||||||
|
|
||||||
# Le système installé doit pouvoir continuer à tirer ses mises à jour
|
# Le système installé doit pouvoir continuer à tirer ses mises à jour
|
||||||
# du repo privé tout seul : on lui laisse un netrc, jamais commité,
|
# du repo privé tout seul : on lui laisse un netrc, jamais commité,
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
i18n.defaultLocale = "fr_FR.UTF-8";
|
i18n.defaultLocale = "fr_FR.UTF-8";
|
||||||
|
# i18n.defaultLocale ne règle pas le clavier de la console — option
|
||||||
|
# séparée, absente jusqu'ici pour ce host (vérifié : wiki.nixos.org/wiki/Keyboard_Layout_Customization).
|
||||||
|
console.keyMap = "fr";
|
||||||
|
|
||||||
boot.loader.systemd-boot.enable = true;
|
boot.loader.systemd-boot.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = true;
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user