feat(system): add zram configuration and enable power-profiles-daemon
- commit
- 731f4562b8d3b88f55aa76b28ef19a62f1a1cad4
- author
- brice · · 2026-02-28 05:22 UTC
- parent
- 01a505a
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +34 -2
M install/extra.packages +1 -1
| @@ -17,7 +17,7 @@ wget | |||
| 17 | 17 | unzip | |
| 18 | 18 | ||
| 19 | 19 | # Power management | |
| 20 | - | tlp | |
| 20 | + | power-profiles-daemon | |
| 21 | 21 | ||
| 22 | 22 | # Security | |
| 23 | 23 | firewalld | |
| @@ -17,7 +17,7 @@ wget | |||||
| 17 | unzip | 17 | unzip | ||
| 18 | 18 | ||||
| 19 | # Power management | 19 | # Power management | ||
| 20 | - | tlp | 20 | + | power-profiles-daemon |
| 21 | 21 | ||||
| 22 | # Security | 22 | # Security | ||
| 23 | firewalld | 23 | firewalld | ||
M internal/application/handlers/configure_system_handler.go +33 -1
| @@ -11,6 +11,7 @@ import ( | |||
| 11 | 11 | ||
| 12 | 12 | "github.com/bnema/archup/internal/application/commands" | |
| 13 | 13 | "github.com/bnema/archup/internal/application/dto" | |
| 14 | + | "github.com/bnema/archup/internal/config" | |
| 14 | 15 | "github.com/bnema/archup/internal/domain/ports" | |
| 15 | 16 | "github.com/bnema/archup/internal/domain/system" | |
| 16 | 17 | "github.com/bnema/archup/internal/domain/user" | |
| @@ -174,7 +175,7 @@ func (h *ConfigureSystemHandler) Handle(ctx context.Context, cmd commands.Config | |||
| 174 | 175 | result.ErrorDetail = fmt.Sprintf("Failed to create sudoers.d directory: %v", err) | |
| 175 | 176 | return result, err | |
| 176 | 177 | } | |
| 177 | - | if err := h.fs.WriteFile(filepath.Join(sudoersDir, "wheel"), []byte("%wheel ALL=(ALL:ALL) ALL\n"), 0440); err != nil { | |
| 178 | + | if err := h.fs.WriteFile(filepath.Join(sudoersDir, "wheel"), []byte(config.SudoersWheelContent), config.SudoersWheelPerms); err != nil { | |
| 178 | 179 | h.logger.Error("Failed to write sudoers", "error", err) | |
| 179 | 180 | result.ErrorDetail = fmt.Sprintf("Failed to write sudoers: %v", err) | |
| 180 | 181 | return result, err | |
| @@ -191,6 +192,14 @@ func (h *ConfigureSystemHandler) Handle(ctx context.Context, cmd commands.Config | |||
| 191 | 192 | h.logger.Warn("Failed to mask NetworkManager-wait-online.service", "error", err) | |
| 192 | 193 | } | |
| 193 | 194 | ||
| 195 | + | if err := h.chrExec.ChrootSystemctl(ctx, h.logger.LogPath(), cmd.MountPoint, "enable", "power-profiles-daemon"); err != nil { | |
| 196 | + | h.logger.Warn("Failed to enable power-profiles-daemon", "error", err) | |
| 197 | + | } | |
| 198 | + | ||
| 199 | + | if err := h.configureZram(cmd.MountPoint); err != nil { | |
| 200 | + | h.logger.Warn("Failed to configure zram", "error", err) | |
| 201 | + | } | |
| 202 | + | ||
| 194 | 203 | // Migrate iwd WiFi credentials from live ISO to NetworkManager profiles in the installed system. | |
| 195 | 204 | if err := h.migrateIWDProfiles(cmd.MountPoint); err != nil { | |
| 196 | 205 | // Non-fatal: log and continue. User can configure WiFi manually after boot. | |
| @@ -364,6 +373,29 @@ func hexNibble(c byte) int { | |||
| 364 | 373 | return -1 | |
| 365 | 374 | } | |
| 366 | 375 | ||
| 376 | + | // configureZram writes zram-generator.conf and the matching sysctl tuning file. | |
| 377 | + | func (h *ConfigureSystemHandler) configureZram(mountPoint string) error { | |
| 378 | + | zramDir := filepath.Join(mountPoint, "etc", "systemd") | |
| 379 | + | if err := h.fs.MkdirAll(zramDir, 0755); err != nil { | |
| 380 | + | return fmt.Errorf("failed to create systemd dir: %w", err) | |
| 381 | + | } | |
| 382 | + | zramConf := filepath.Join(zramDir, config.FileZramGenerator) | |
| 383 | + | if err := h.fs.WriteFile(zramConf, []byte(config.ZramConfigContent), 0644); err != nil { | |
| 384 | + | return fmt.Errorf("failed to write zram-generator.conf: %w", err) | |
| 385 | + | } | |
| 386 | + | ||
| 387 | + | sysctlDir := filepath.Join(mountPoint, "etc", "sysctl.d") | |
| 388 | + | if err := h.fs.MkdirAll(sysctlDir, 0755); err != nil { | |
| 389 | + | return fmt.Errorf("failed to create sysctl.d dir: %w", err) | |
| 390 | + | } | |
| 391 | + | sysctlConf := filepath.Join(sysctlDir, config.FileSysctlZramParams) | |
| 392 | + | if err := h.fs.WriteFile(sysctlConf, []byte(config.ZramSysctlContent), 0644); err != nil { | |
| 393 | + | return fmt.Errorf("failed to write zram sysctl params: %w", err) | |
| 394 | + | } | |
| 395 | + | ||
| 396 | + | return nil | |
| 397 | + | } | |
| 398 | + | ||
| 367 | 399 | // buildNMWiFiProfile generates a NetworkManager keyfile for a WPA-PSK network. | |
| 368 | 400 | func buildNMWiFiProfile(ssid, psk string) string { | |
| 369 | 401 | return fmt.Sprintf(`[connection] | |
| @@ -11,6 +11,7 @@ import ( | |||||
| 11 | 11 | ||||
| 12 | "github.com/bnema/archup/internal/application/commands" | 12 | "github.com/bnema/archup/internal/application/commands" | ||
| 13 | "github.com/bnema/archup/internal/application/dto" | 13 | "github.com/bnema/archup/internal/application/dto" | ||
| 14 | + | "github.com/bnema/archup/internal/config" | |||
| 14 | "github.com/bnema/archup/internal/domain/ports" | 15 | "github.com/bnema/archup/internal/domain/ports" | ||
| 15 | "github.com/bnema/archup/internal/domain/system" | 16 | "github.com/bnema/archup/internal/domain/system" | ||
| 16 | "github.com/bnema/archup/internal/domain/user" | 17 | "github.com/bnema/archup/internal/domain/user" | ||
| @@ -174,7 +175,7 @@ func (h *ConfigureSystemHandler) Handle(ctx context.Context, cmd commands.Config | |||||
| 174 | result.ErrorDetail = fmt.Sprintf("Failed to create sudoers.d directory: %v", err) | 175 | result.ErrorDetail = fmt.Sprintf("Failed to create sudoers.d directory: %v", err) | ||
| 175 | return result, err | 176 | return result, err | ||
| 176 | } | 177 | } | ||
| 177 | - | if err := h.fs.WriteFile(filepath.Join(sudoersDir, "wheel"), []byte("%wheel ALL=(ALL:ALL) ALL\n"), 0440); err != nil { | 178 | + | if err := h.fs.WriteFile(filepath.Join(sudoersDir, "wheel"), []byte(config.SudoersWheelContent), config.SudoersWheelPerms); err != nil { |
| 178 | h.logger.Error("Failed to write sudoers", "error", err) | 179 | h.logger.Error("Failed to write sudoers", "error", err) | ||
| 179 | result.ErrorDetail = fmt.Sprintf("Failed to write sudoers: %v", err) | 180 | result.ErrorDetail = fmt.Sprintf("Failed to write sudoers: %v", err) | ||
| 180 | return result, err | 181 | return result, err | ||
| @@ -191,6 +192,14 @@ func (h *ConfigureSystemHandler) Handle(ctx context.Context, cmd commands.Config | |||||
| 191 | h.logger.Warn("Failed to mask NetworkManager-wait-online.service", "error", err) | 192 | h.logger.Warn("Failed to mask NetworkManager-wait-online.service", "error", err) | ||
| 192 | } | 193 | } | ||
| 193 | 194 | ||||
| 195 | + | if err := h.chrExec.ChrootSystemctl(ctx, h.logger.LogPath(), cmd.MountPoint, "enable", "power-profiles-daemon"); err != nil { | |||
| 196 | + | h.logger.Warn("Failed to enable power-profiles-daemon", "error", err) | |||
| 197 | + | } | |||
| 198 | + | ||||
| 199 | + | if err := h.configureZram(cmd.MountPoint); err != nil { | |||
| 200 | + | h.logger.Warn("Failed to configure zram", "error", err) | |||
| 201 | + | } | |||
| 202 | + | ||||
| 194 | // Migrate iwd WiFi credentials from live ISO to NetworkManager profiles in the installed system. | 203 | // Migrate iwd WiFi credentials from live ISO to NetworkManager profiles in the installed system. | ||
| 195 | if err := h.migrateIWDProfiles(cmd.MountPoint); err != nil { | 204 | if err := h.migrateIWDProfiles(cmd.MountPoint); err != nil { | ||
| 196 | // Non-fatal: log and continue. User can configure WiFi manually after boot. | 205 | // Non-fatal: log and continue. User can configure WiFi manually after boot. | ||
| @@ -364,6 +373,29 @@ func hexNibble(c byte) int { | |||||
| 364 | return -1 | 373 | return -1 | ||
| 365 | } | 374 | } | ||
| 366 | 375 | ||||
| 376 | + | // configureZram writes zram-generator.conf and the matching sysctl tuning file. | |||
| 377 | + | func (h *ConfigureSystemHandler) configureZram(mountPoint string) error { | |||
| 378 | + | zramDir := filepath.Join(mountPoint, "etc", "systemd") | |||
| 379 | + | if err := h.fs.MkdirAll(zramDir, 0755); err != nil { | |||
| 380 | + | return fmt.Errorf("failed to create systemd dir: %w", err) | |||
| 381 | + | } | |||
| 382 | + | zramConf := filepath.Join(zramDir, config.FileZramGenerator) | |||
| 383 | + | if err := h.fs.WriteFile(zramConf, []byte(config.ZramConfigContent), 0644); err != nil { | |||
| 384 | + | return fmt.Errorf("failed to write zram-generator.conf: %w", err) | |||
| 385 | + | } | |||
| 386 | + | ||||
| 387 | + | sysctlDir := filepath.Join(mountPoint, "etc", "sysctl.d") | |||
| 388 | + | if err := h.fs.MkdirAll(sysctlDir, 0755); err != nil { | |||
| 389 | + | return fmt.Errorf("failed to create sysctl.d dir: %w", err) | |||
| 390 | + | } | |||
| 391 | + | sysctlConf := filepath.Join(sysctlDir, config.FileSysctlZramParams) | |||
| 392 | + | if err := h.fs.WriteFile(sysctlConf, []byte(config.ZramSysctlContent), 0644); err != nil { | |||
| 393 | + | return fmt.Errorf("failed to write zram sysctl params: %w", err) | |||
| 394 | + | } | |||
| 395 | + | ||||
| 396 | + | return nil | |||
| 397 | + | } | |||
| 398 | + | ||||
| 367 | // buildNMWiFiProfile generates a NetworkManager keyfile for a WPA-PSK network. | 399 | // buildNMWiFiProfile generates a NetworkManager keyfile for a WPA-PSK network. | ||
| 368 | func buildNMWiFiProfile(ssid, psk string) string { | 400 | func buildNMWiFiProfile(ssid, psk string) string { | ||
| 369 | return fmt.Sprintf(`[connection] | 401 | return fmt.Sprintf(`[connection] | ||