Last active 4 days ago

Hardened install scripts with an interactive menu — Chrome, Firefox, Thunderbird, 1Password, Espanso, LibreOffice, Obsidian, draw.io Desktop, VS Code, JetBrains Toolbox, Bruno, IPATool, Synology NAS auto-mount, IBus Pinyin, Nerd Fonts, qBittorrent LocalSend Telegram Discord.

weehong revised this gist 2 weeks ago. Go to revision

1 file changed, 12 insertions, 3 deletions

install-espanso.sh

@@ -1,7 +1,7 @@
1 1 #!/usr/bin/env bash
2 2 # install-espanso.sh — Install Espanso (text expander) with Wayland or X11 build.
3 3 # Auto-detects session type; falls back to X11 if Wayland is not active.
4 - # Hardened: session detection, registers service as the invoking user, idempotent.
4 + # Hardened: handles apt temp file permissions, package collisions, and ghost processes.
5 5
6 6 set -euo pipefail
7 7 IFS=$'\n\t'
@@ -76,6 +76,8 @@ log "Detected: ${PRETTY_NAME:-unknown}, user: $ACTUAL_USER, session: $VARIANT"
76 76
77 77 export DEBIAN_FRONTEND=noninteractive
78 78 TEMP_DEB="$(mktemp -t espanso.XXXXXX.deb)"
79 + # Ensure the _apt user can read the temporary file to prevent permission denied errors
80 + chmod 644 "$TEMP_DEB"
79 81 trap 'rm -f "$TEMP_DEB"' EXIT
80 82
81 83 DEB_NAME="espanso-debian-${VARIANT}-amd64.deb"
@@ -83,11 +85,15 @@ URL="https://github.com/espanso/espanso/releases/latest/download/${DEB_NAME}"
83 85
84 86 log "Installing prerequisites..."
85 87 run "apt-get update -qq"
86 - run "apt-get install -y wget libcap2-bin"
88 + run "apt-get install -y wget libcap2-bin psmisc"
87 89
88 90 log "Downloading ${DEB_NAME}..."
89 91 run "wget -qO '$TEMP_DEB' '$URL'"
90 92
93 + log "Removing conflicting Espanso packages (if any)..."
94 + # Suppress output and errors if packages don't exist
95 + run "apt-get remove -y espanso espanso-wayland >/dev/null 2>&1 || true"
96 +
91 97 log "Installing package..."
92 98 run "apt-get install -y '$TEMP_DEB'"
93 99
@@ -99,6 +105,9 @@ if [[ "$VARIANT" == "wayland" ]]; then
99 105 run "setcap 'cap_dac_override+p' '$ESPANSO_BIN'"
100 106 fi
101 107
108 + log "Clearing ghost processes to prevent start timeouts..."
109 + run "sudo -u '$ACTUAL_USER' killall espanso 2>/dev/null || true"
110 +
102 111 log "Registering & starting espanso service for $ACTUAL_USER..."
103 112 # Register may fail if already registered — treat that as success.
104 113 if (( DRY_RUN )); then
@@ -113,4 +122,4 @@ fi
113 122 log "Done. Espanso ($VARIANT) installed and started for $ACTUAL_USER."
114 123 if [[ "$VARIANT" == "wayland" ]]; then
115 124 log "Wayland note: non-US keyboards must set the layout in ~/.config/espanso/config/default.yml"
116 - fi
125 + fi

weehong revised this gist 3 weeks ago. Go to revision

3 files changed, 88 insertions, 45 deletions

READMD.md renamed to README.md

@@ -16,7 +16,7 @@ How to use the picker:
16 16 - `0` runs every option in order
17 17 - `-1` exits
18 18
19 - The menu caches `sudo` credentials up-front so multi-task runs don't keep re-prompting, and falls back to per-user execution for the three scripts that must not run as root (JetBrains Toolbox, IBus Pinyin, Ubuntu Sans Nerd Font).
19 + The menu caches `sudo` credentials up-front so multi-task runs don't keep re-prompting, and falls back to per-user execution for the three scripts that must not run as root (JetBrains Toolbox, IBus Pinyin, Nerd Fonts).
20 20
21 21 ## Available scripts
22 22
@@ -33,7 +33,7 @@ The menu caches `sudo` credentials up-front so multi-task runs don't keep re-pro
33 33 | 9 | [`install-ipatool.sh`](install-ipatool.sh) | sudo | Installs the latest release of `majd/ipatool` from GitHub. SHA-256 verified against the release `checksums.txt`. Honors `$GITHUB_TOKEN` to avoid API rate limits. |
34 34 | 10 | [`install-network_drive.sh`](install-network_drive.sh) | sudo | Discovers SMB shares on a Synology NAS and adds them to `/etc/fstab` under `/mnt/Synology` with `x-systemd.automount`. fstab block is managed via begin/end markers so re-runs replace rather than duplicate. Credentials file is `0600`. Best-effort GNOME Dock pin. |
35 35 | 11 | [`install-ibus-pinyin.sh`](install-ibus-pinyin.sh) | **user** | Installs `ibus-libpinyin` and Simplified Chinese language packs, restarts the IBus daemon, and idempotently adds `('ibus', 'libpinyin')` to GNOME's input sources via `gsettings`. |
36 - | 12 | [`install_font.sh`](install_font.sh) | **user** | Installs the latest Ubuntu Sans Nerd Font to `~/.local/share/fonts/UbuntuSans` and refreshes the font cache. No sudo needed. |
36 + | 12 | [`install-font.sh`](install-font.sh) | **user** | Installs the latest Ubuntu Sans Nerd Font and JetBrains Mono Nerd Font to `~/.local/share/fonts`, then refreshes the font cache. No sudo needed. |
37 37
38 38 "Runs as **user**" entries must be invoked as your normal desktop user, not via `sudo`. The other entries elevate via `sudo` internally and the menu primes `sudo -v` up-front, so you'll only be prompted once.
39 39
@@ -46,7 +46,7 @@ If you'd rather skip the menu, each script can be run on its own. Use the right
46 46 curl -fsSL https://opengist.rmrf.online/weehong/2de15ba0106a475fa41215159203a63b/raw/HEAD/install-firefox.sh | sudo bash
47 47
48 48 # user scripts (7, 11, 12) — DO NOT use sudo; they install per-user
49 - bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/2de15ba0106a475fa41215159203a63b/raw/HEAD/install_font.sh)"
49 + bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/2de15ba0106a475fa41215159203a63b/raw/HEAD/install-font.sh)"
50 50 ```
51 51
52 52 Every script accepts `--help` and `--dry-run` (the latter prints what would happen without executing). For example:

install-font.sh

@@ -1,54 +1,97 @@
1 - #!/bin/bash
1 + #!/usr/bin/env bash
2 2
3 - # Exit immediately if a command exits with a non-zero status
4 - set -e
3 + set -euo pipefail
4 + IFS=$'\n\t'
5 5
6 - FONT_NAME="UbuntuSans"
7 - FONT_ZIP="${FONT_NAME}.zip"
8 - # Simplified directory: removed the "NerdFonts" subfolder
9 - FONT_DIR="$HOME/.local/share/fonts/${FONT_NAME}"
10 - TMP_DIR=$(mktemp -d)
6 + readonly SCRIPT_NAME="${0##*/}"
7 + readonly FONT_BASE_DIR="$HOME/.local/share/fonts"
8 + readonly TMP_DIR="$(mktemp -d)"
11 9
12 - echo "Searching for the latest release of $FONT_NAME Nerd Font..."
10 + log() { printf '\033[1;34m[%s]\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*"; }
11 + warn() { printf '\033[1;33m[%s] WARN:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; }
12 + die() { printf '\033[1;31m[%s] ERROR:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; exit 1; }
13 13
14 - # Use GitHub API to find the latest release download URL for UbuntuSans.zip
15 - DOWNLOAD_URL=$(curl -s https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest \
16 - | grep "browser_download_url.*${FONT_ZIP}" \
17 - | cut -d '"' -f 4)
14 + cleanup() {
15 + rm -rf "$TMP_DIR"
16 + }
17 + trap cleanup EXIT
18 18
19 - if [ -z "$DOWNLOAD_URL" ]; then
20 - echo "Error: Could not find the download URL for $FONT_NAME. Check your internet connection or GitHub API limits."
21 - rm -rf "$TMP_DIR"
22 - exit 1
19 + if (( EUID == 0 )); then
20 + die "Do not run as root. Run as your normal desktop user so fonts install under $HOME."
23 21 fi
24 22
25 - echo "Latest version found!"
26 - echo "Downloading from: $DOWNLOAD_URL"
23 + for tool in curl unzip fc-cache find; do
24 + command -v "$tool" >/dev/null 2>&1 || die "Missing required tool: $tool"
25 + done
27 26
28 - # Download the zip file to the temporary directory
29 - curl -L -q "$DOWNLOAD_URL" -o "$TMP_DIR/$FONT_ZIP"
27 + latest_nerd_font_url() {
28 + local asset_name="$1"
29 + local url
30 30
31 - echo "Extracting fonts..."
32 - # Ensure unzip is installed (will fail gracefully if not)
33 - if ! command -v unzip &> /dev/null; then
34 - echo "Error: 'unzip' is not installed. Please install it using 'sudo apt install unzip' and try again."
35 - rm -rf "$TMP_DIR"
36 - exit 1
37 - fi
31 + url="$(
32 + curl -fsSL https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest \
33 + | grep "browser_download_url.*${asset_name}" \
34 + | cut -d '"' -f 4 \
35 + | head -n 1 \
36 + || true
37 + )"
38 +
39 + [[ -n "$url" ]] || die "Could not find download URL for $asset_name. Check connectivity or GitHub API limits."
40 + printf '%s' "$url"
41 + }
42 +
43 + install_nerd_font() {
44 + local display_name="$1"
45 + local asset_name="$2"
46 + local font_dir="$3"
47 + local download_url="$4"
48 + local zip_path="$TMP_DIR/${asset_name}.zip"
49 + local extract_dir="$TMP_DIR/${asset_name}"
50 + local installed_count
51 +
52 + if [[ -z "$download_url" ]]; then
53 + log "Finding latest $display_name release..."
54 + download_url="$(latest_nerd_font_url "${asset_name}.zip")"
55 + fi
56 +
57 + log "Downloading $display_name..."
58 + curl -fL --retry 3 --retry-delay 2 -o "$zip_path" "$download_url"
38 59
39 - unzip -q -o "$TMP_DIR/$FONT_ZIP" -d "$TMP_DIR/extracted"
60 + log "Extracting $display_name..."
61 + mkdir -p "$extract_dir" "$font_dir"
62 + unzip -q -o "$zip_path" -d "$extract_dir"
40 63
41 - echo "Installing fonts to $FONT_DIR..."
42 - # Create the simplified font directory if it doesn't exist
43 - mkdir -p "$FONT_DIR"
64 + installed_count="$(
65 + find "$extract_dir" -type f \( -name '*.ttf' -o -name '*.otf' \) \
66 + -exec cp {} "$font_dir/" \; \
67 + -printf '.' \
68 + | wc -c
69 + )"
44 70
45 - # Move only the TrueType (.ttf) or OpenType (.otf) files to the fonts directory
46 - find "$TMP_DIR/extracted" -name '*.[ot]tf' -type f -exec cp {} "$FONT_DIR/" \;
71 + [[ "$installed_count" -gt 0 ]] || die "No font files found in ${asset_name}.zip"
72 + find "$font_dir" -type f \( -name '*.ttf' -o -name '*.otf' \) -exec chmod 0644 {} +
73 + log "Installed $installed_count font files to $font_dir"
74 + }
47 75
48 - echo "Updating the system font cache..."
49 - fc-cache -f "$FONT_DIR"
76 + mkdir -p "$FONT_BASE_DIR"
50 77
51 - echo "Cleaning up temporary files..."
52 - rm -rf "$TMP_DIR"
78 + install_nerd_font \
79 + "Ubuntu Sans Nerd Font" \
80 + "UbuntuSans" \
81 + "$FONT_BASE_DIR/UbuntuSans" \
82 + ""
83 +
84 + install_nerd_font \
85 + "JetBrains Mono Nerd Font" \
86 + "JetBrainsMono" \
87 + "$FONT_BASE_DIR/JetBrainsMonoNerdFont" \
88 + ""
89 +
90 + log "Updating font cache..."
91 + fc-cache -f "$FONT_BASE_DIR"
92 +
93 + if command -v fc-match >/dev/null 2>&1; then
94 + log "Resolved terminal font: $(fc-match 'JetBrainsMono Nerd Font Mono')"
95 + fi
53 96
54 - echo "Done! $FONT_NAME Nerd Font has been successfully installed."
97 + log "Done. Configure your terminal to use JetBrainsMono Nerd Font Mono for Starship Powerline symbols."

menu.sh

@@ -118,7 +118,7 @@ OPTIONS=(
118 118 "10|Install IPATool|install-ipatool.sh|sudo"
119 119 "11|Mount Synology Network Drive|install-network_drive.sh|sudo"
120 120 "12|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user"
121 - "13|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user"
121 + "13|Install Nerd Fonts (per-user)|install-font.sh|user"
122 122 "14|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo"
123 123 )
124 124
@@ -142,7 +142,7 @@ print_menu() {
142 142 echo "--- [ System ] ---"
143 143 echo " 11) Mount Synology Network Drive"
144 144 echo " 12) Install IBus Intelligent Pinyin (runs as you, not root)"
145 - echo " 13) Install Ubuntu Sans Nerd Font (runs as you, not root)"
145 + echo " 13) Install Nerd Fonts (runs as you, not root)"
146 146 echo " 14) Fix Dual-Boot Time (RTC to UTC)"
147 147 hr
148 148 echo " 0) Run ALL options (1-14)"
@@ -226,4 +226,4 @@ while true; do
226 226 warn "Completed with ${#failures[@]} failure(s): ${failures[*]}"
227 227 fi
228 228 echo
229 - done
229 + done

weehong revised this gist 3 weeks ago. Go to revision

No changes

weehong revised this gist 3 weeks ago. Go to revision

1 file changed, 47 insertions

install-chrome.sh(file created)

@@ -0,0 +1,47 @@
1 + #!/usr/bin/env bash
2 + #
3 + # install-chrome.sh — Native Google Chrome Installer for Ubuntu/Debian
4 + # Downloads and installs the latest official stable release without Snap.
5 + #
6 + # Usage:
7 + # sudo ./install-chrome.sh
8 +
9 + set -euo pipefail
10 + IFS=$'\n\t'
11 +
12 + # Ensure the script is run as root
13 + if (( EUID != 0 )); then
14 + echo "[ERROR] This script must be run as root (via sudo)." >&2
15 + exit 1
16 + fi
17 +
18 + echo "[1/4] Installing necessary prerequisites..."
19 + apt-get update -y
20 + apt-get install -y curl gnupg2 ca-certificates
21 +
22 + echo "[2/4] Setting up Google's official repository keys..."
23 + # Create directory for Third-Party APT keys if it doesn't exist
24 + install -d -m 0755 /etc/apt/keyrings
25 +
26 + # Fetch the official signing key and save it securely
27 + curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | \
28 + gpg --dearmor --yes -o /etc/apt/keyrings/google-chrome.gpg
29 +
30 + # Configure the APT repository to strictly use that signing key
31 + echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \
32 + > /etc/apt/sources.list.d/google-chrome.list
33 +
34 + echo "[3/4] Fetching package lists and installing Google Chrome..."
35 + apt-get update -y
36 + apt-get install -y google-chrome-stable
37 +
38 + echo "[4/4] Verifying installation..."
39 + if command -v google-chrome &>/dev/null; then
40 + echo "------------------------------------------------------"
41 + echo "SUCCESS: Google Chrome has been installed successfully!"
42 + echo "Version: $(google-chrome --version)"
43 + echo "------------------------------------------------------"
44 + else
45 + echo "[ERROR] Google Chrome installation could not be verified." >&2
46 + exit 1
47 + fi

weehong revised this gist 3 weeks ago. Go to revision

1 file changed, 31 insertions, 29 deletions

menu.sh

@@ -106,19 +106,20 @@ run_script() {
106 106 # Catalog: number | label | script-filename | mode
107 107 # (Edit here to add/remove options — the menu loop is data-driven.)
108 108 OPTIONS=(
109 - "1|Install Firefox (Mozilla APT)|install-firefox.sh|sudo"
110 - "2|Install Thunderbird|install-thunderbird.sh|sudo"
111 - "3|Install 1Password|install-1password.sh|sudo"
112 - "4|Install Espanso (text expander)|install-espanso.sh|sudo"
113 - "5|Install LibreOffice (latest stable .deb)|install-libreoffice.sh|sudo"
114 - "6|Install Visual Studio Code|install-vscode.sh|sudo"
115 - "7|Install JetBrains Toolbox (per-user)|install-jetbrains-toolbox.sh|user"
116 - "8|Install Bruno (API client)|install-bruno.sh|sudo"
117 - "9|Install IPATool|install-ipatool.sh|sudo"
118 - "10|Mount Synology Network Drive|install-network_drive.sh|sudo"
119 - "11|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user"
120 - "12|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user"
121 - "13|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo"
109 + "1|Install Google Chrome|install-chrome.sh|sudo"
110 + "2|Install Firefox (Mozilla APT)|install-firefox.sh|sudo"
111 + "3|Install Thunderbird|install-thunderbird.sh|sudo"
112 + "4|Install 1Password|install-1password.sh|sudo"
113 + "5|Install Espanso (text expander)|install-espanso.sh|sudo"
114 + "6|Install LibreOffice (latest stable .deb)|install-libreoffice.sh|sudo"
115 + "7|Install Visual Studio Code|install-vscode.sh|sudo"
116 + "8|Install JetBrains Toolbox (per-user)|install-jetbrains-toolbox.sh|user"
117 + "9|Install Bruno (API client)|install-bruno.sh|sudo"
118 + "10|Install IPATool|install-ipatool.sh|sudo"
119 + "11|Mount Synology Network Drive|install-network_drive.sh|sudo"
120 + "12|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user"
121 + "13|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user"
122 + "14|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo"
122 123 )
123 124
124 125 print_menu() {
@@ -126,24 +127,25 @@ print_menu() {
126 127 echo " Ubuntu / Debian Setup Manager"
127 128 hr
128 129 echo "--- [ Browsers & Mail ] ---"
129 - echo " 1) Install Firefox"
130 - echo " 2) Install Thunderbird"
130 + echo " 1) Install Google Chrome"
131 + echo " 2) Install Firefox"
132 + echo " 3) Install Thunderbird"
131 133 echo "--- [ Productivity & Security ] ---"
132 - echo " 3) Install 1Password"
133 - echo " 4) Install Espanso"
134 - echo " 5) Install LibreOffice"
134 + echo " 4) Install 1Password"
135 + echo " 5) Install Espanso"
136 + echo " 6) Install LibreOffice"
135 137 echo "--- [ Development Tools ] ---"
136 - echo " 6) Install Visual Studio Code"
137 - echo " 7) Install JetBrains Toolbox (runs as you, not root)"
138 - echo " 8) Install Bruno"
139 - echo " 9) Install IPATool"
138 + echo " 7) Install Visual Studio Code"
139 + echo " 8) Install JetBrains Toolbox (runs as you, not root)"
140 + echo " 9) Install Bruno"
141 + echo " 10) Install IPATool"
140 142 echo "--- [ System ] ---"
141 - echo " 10) Mount Synology Network Drive"
142 - echo " 11) Install IBus Intelligent Pinyin (runs as you, not root)"
143 - echo " 12) Install Ubuntu Sans Nerd Font (runs as you, not root)"
144 - echo " 13) Fix Dual-Boot Time (RTC to UTC)"
143 + echo " 11) Mount Synology Network Drive"
144 + echo " 12) Install IBus Intelligent Pinyin (runs as you, not root)"
145 + echo " 13) Install Ubuntu Sans Nerd Font (runs as you, not root)"
146 + echo " 14) Fix Dual-Boot Time (RTC to UTC)"
145 147 hr
146 - echo " 0) Run ALL options (1-13)"
148 + echo " 0) Run ALL options (1-14)"
147 149 echo " -1) Exit"
148 150 hr
149 151 }
@@ -162,13 +164,13 @@ resolve_choice() {
162 164 return 1
163 165 }
164 166
165 - ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12 13)
167 + ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12 13 14)
166 168
167 169 prime_sudo || exit 1
168 170
169 171 while true; do
170 172 print_menu
171 - read -rp "Enter choices separated by spaces (e.g., 1 6 11), 0 for ALL, -1 to exit: " choices </dev/tty || {
173 + read -rp "Enter choices separated by spaces (e.g., 1 7 12), 0 for ALL, -1 to exit: " choices </dev/tty || {
172 174 echo; log "Input closed; exiting."
173 175 break
174 176 }

weehong revised this gist 3 weeks ago. Go to revision

1 file changed, 15 insertions, 16 deletions

timedatectl-fix.sh

@@ -4,7 +4,7 @@ set -euo pipefail
4 4
5 5 echo "======================================"
6 6 echo " Ubuntu Dual-Boot Time Fix Script"
7 - echo " (Local Time Method)"
7 + echo " (UTC Method - Highly Recommended)"
8 8 echo "======================================"
9 9 echo
10 10
@@ -21,9 +21,9 @@ CURRENT_TZ=$(timedatectl show -p Timezone --value || echo "UTC")
21 21 echo "[1/5] Ensuring timezone is set to $CURRENT_TZ..."
22 22 timedatectl set-timezone "$CURRENT_TZ"
23 23
24 - echo "[2/5] Configuring RTC to use Local Time (to match Windows default)..."
25 - # This is the crucial change: '1' sets it to Local Time
26 - timedatectl set-local-rtc 1 --adjust-system-clock
24 + echo "[2/5] Configuring RTC to use UTC (to prevent dual-boot conflicts)..."
25 + # '0' sets the hardware clock to UTC
26 + timedatectl set-local-rtc 0 --adjust-system-clock
27 27
28 28 echo "[3/5] Enabling NTP synchronization..."
29 29 timedatectl set-ntp true
@@ -37,29 +37,28 @@ timedatectl
37 37
38 38 echo
39 39 echo "======================================"
40 - echo " SUCCESS"
40 + echo " SUCCESS - LINUX CONFIGURED"
41 41 echo "======================================"
42 42 echo
43 43 echo "Your system is now configured with:"
44 44 echo " - Timezone: $CURRENT_TZ"
45 - echo " - RTC stored in Local Time"
45 + echo " - RTC stored in UTC"
46 46 echo " - NTP synchronization enabled"
47 47 echo
48 - echo "Note: You can safely ignore any 'RTC in local TZ' warnings"
49 - echo "from timedatectl, as they are expected with this configuration."
50 - echo
51 48
52 49 cat <<'EOF'
53 50 --------------------------------------------------
54 - WINDOWS CONFIGURATION (IF NEEDED)
51 + WINDOWS CONFIGURATION (REQUIRED)
55 52 --------------------------------------------------
56 - Linux is now expecting the hardware clock to be in Local Time,
57 - which is the default behavior for Windows.
53 + Linux is now correctly expecting the hardware clock to be in UTC.
54 + To make Windows do the same and stop the time from resetting,
55 + you MUST run the following command in Windows.
58 56
59 - If you previously added a registry key to force Windows into UTC,
60 - you must remove it. Run this in Windows Administrator CMD:
57 + 1. Boot into Windows.
58 + 2. Open Command Prompt as Administrator.
59 + 3. Run this exact command:
61 60
62 - reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /f
61 + reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f
63 62
64 - If you never changed Windows time settings, you are completely done!
63 + 4. Restart Windows and sync the time in Settings one last time.
65 64 EOF

weehong revised this gist 3 weeks ago. Go to revision

1 file changed, 15 insertions, 11 deletions

timedatectl-fix.sh

@@ -3,7 +3,8 @@
3 3 set -euo pipefail
4 4
5 5 echo "======================================"
6 - echo " Linux Dual-Boot Time Fix Script"
6 + echo " Ubuntu Dual-Boot Time Fix Script"
7 + echo " (Local Time Method)"
7 8 echo "======================================"
8 9 echo
9 10
@@ -20,8 +21,9 @@ CURRENT_TZ=$(timedatectl show -p Timezone --value || echo "UTC")
20 21 echo "[1/5] Ensuring timezone is set to $CURRENT_TZ..."
21 22 timedatectl set-timezone "$CURRENT_TZ"
22 23
23 - echo "[2/5] Configuring RTC to use UTC..."
24 - timedatectl set-local-rtc 0
24 + echo "[2/5] Configuring RTC to use Local Time (to match Windows default)..."
25 + # This is the crucial change: '1' sets it to Local Time
26 + timedatectl set-local-rtc 1 --adjust-system-clock
25 27
26 28 echo "[3/5] Enabling NTP synchronization..."
27 29 timedatectl set-ntp true
@@ -40,22 +42,24 @@ echo "======================================"
40 42 echo
41 43 echo "Your system is now configured with:"
42 44 echo " - Timezone: $CURRENT_TZ"
43 - echo " - RTC stored in UTC"
45 + echo " - RTC stored in Local Time"
44 46 echo " - NTP synchronization enabled"
45 47 echo
46 - echo "This is the recommended setup for Linux."
48 + echo "Note: You can safely ignore any 'RTC in local TZ' warnings"
49 + echo "from timedatectl, as they are expected with this configuration."
47 50 echo
48 51
49 52 cat <<'EOF'
50 53 --------------------------------------------------
51 - WINDOWS CONFIGURATION REQUIRED
54 + WINDOWS CONFIGURATION (IF NEEDED)
52 55 --------------------------------------------------
53 - If you dual-boot with Windows, configure Windows
54 - to also use UTC to prevent clock drift.
56 + Linux is now expecting the hardware clock to be in Local Time,
57 + which is the default behavior for Windows.
55 58
56 - Run this in Windows Administrator CMD:
59 + If you previously added a registry key to force Windows into UTC,
60 + you must remove it. Run this in Windows Administrator CMD:
57 61
58 - reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /t REG_DWORD /d 1 /f
62 + reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /f
59 63
60 - Then reboot Windows once.
64 + If you never changed Windows time settings, you are completely done!
61 65 EOF

weehong revised this gist 4 weeks ago. Go to revision

2 files changed, 6 insertions, 4 deletions

install_font.sh renamed to install-font.sh

File renamed without changes

menu.sh

@@ -117,7 +117,8 @@ OPTIONS=(
117 117 "9|Install IPATool|install-ipatool.sh|sudo"
118 118 "10|Mount Synology Network Drive|install-network_drive.sh|sudo"
119 119 "11|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user"
120 - "12|Install Ubuntu Sans Nerd Font (per-user)|install_font.sh|user"
120 + "12|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user"
121 + "13|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo"
121 122 )
122 123
123 124 print_menu() {
@@ -140,8 +141,9 @@ print_menu() {
140 141 echo " 10) Mount Synology Network Drive"
141 142 echo " 11) Install IBus Intelligent Pinyin (runs as you, not root)"
142 143 echo " 12) Install Ubuntu Sans Nerd Font (runs as you, not root)"
144 + echo " 13) Fix Dual-Boot Time (RTC to UTC)"
143 145 hr
144 - echo " 0) Run ALL options (1-12)"
146 + echo " 0) Run ALL options (1-13)"
145 147 echo " -1) Exit"
146 148 hr
147 149 }
@@ -160,7 +162,7 @@ resolve_choice() {
160 162 return 1
161 163 }
162 164
163 - ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12)
165 + ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12 13)
164 166
165 167 prime_sudo || exit 1
166 168
@@ -222,4 +224,4 @@ while true; do
222 224 warn "Completed with ${#failures[@]} failure(s): ${failures[*]}"
223 225 fi
224 226 echo
225 - done
227 + done

weehong revised this gist 4 weeks ago. Go to revision

1 file changed, 61 insertions

timedatectl-fix.sh(file created)

@@ -0,0 +1,61 @@
1 + #!/usr/bin/env bash
2 +
3 + set -euo pipefail
4 +
5 + echo "======================================"
6 + echo " Linux Dual-Boot Time Fix Script"
7 + echo "======================================"
8 + echo
9 +
10 + # Ensure running as root
11 + if [[ $EUID -ne 0 ]]; then
12 + echo "Please run as root:"
13 + echo "sudo bash fix-time.sh"
14 + exit 1
15 + fi
16 +
17 + # Detect current timezone instead of hardcoding
18 + CURRENT_TZ=$(timedatectl show -p Timezone --value || echo "UTC")
19 +
20 + echo "[1/5] Ensuring timezone is set to $CURRENT_TZ..."
21 + timedatectl set-timezone "$CURRENT_TZ"
22 +
23 + echo "[2/5] Configuring RTC to use UTC..."
24 + timedatectl set-local-rtc 0
25 +
26 + echo "[3/5] Enabling NTP synchronization..."
27 + timedatectl set-ntp true
28 +
29 + echo "[4/5] Restarting time sync daemon (if applicable)..."
30 + systemctl restart systemd-timesyncd 2>/dev/null || true
31 +
32 + echo "[5/5] Final time configuration:"
33 + echo
34 + timedatectl
35 +
36 + echo
37 + echo "======================================"
38 + echo " SUCCESS"
39 + echo "======================================"
40 + echo
41 + echo "Your system is now configured with:"
42 + echo " - Timezone: $CURRENT_TZ"
43 + echo " - RTC stored in UTC"
44 + echo " - NTP synchronization enabled"
45 + echo
46 + echo "This is the recommended setup for Linux."
47 + echo
48 +
49 + cat <<'EOF'
50 + --------------------------------------------------
51 + WINDOWS CONFIGURATION REQUIRED
52 + --------------------------------------------------
53 + If you dual-boot with Windows, configure Windows
54 + to also use UTC to prevent clock drift.
55 +
56 + Run this in Windows Administrator CMD:
57 +
58 + reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /t REG_DWORD /d 1 /f
59 +
60 + Then reboot Windows once.
61 + EOF

weehong revised this gist 1 month ago. Go to revision

No changes

Newer Older