Arch Linux Setup and Configuration
This is my collection of Arch Linux configurations and commands that I use to maintain and optimize my system.
Battery Management
Charge Control Thresholds
To extend battery lifespan, you can configure charge thresholds that prevent the battery from charging to 100% when plugged in constantly:
echo 45 | sudo tee /sys/class/power_supply/BAT0/charge_control_start_threshold
echo 55 | sudo tee /sys/class/power_supply/BAT0/charge_control_end_threshold
This configuration starts charging at 45% and stops at 55%, ideal for a laptop that stays plugged in most of the time.
Convenience Functions for .bashrc
Add these functions to your ~/.bashrc file for quick threshold switching:
setbattery50() {
echo 45 | sudo tee /sys/class/power_supply/BAT0/charge_control_start_threshold > /dev/null
echo 55 | sudo tee /sys/class/power_supply/BAT0/charge_control_end_threshold > /dev/null
echo "Charging range set from 45% to 55%"
}
setbattery100() {
echo 0 | sudo tee /sys/class/power_supply/BAT0/charge_control_start_threshold > /dev/null
echo 100 | sudo tee /sys/class/power_supply/BAT0/charge_control_end_threshold > /dev/null
echo "Charging range set from 0% to 100%"
}
Usage:
setbattery50- Sets conservative 45-55% charging range. Use this when your laptop stays plugged in most of the time (desk setup). This significantly extends battery lifespan by avoiding the stress of maintaining a full charge.setbattery100- Restores full 0-100% charging range. Use this when you need maximum battery capacity for mobile use or before traveling.
After adding these to .bashrc, run source ~/.bashrc to load them, then simply type setbattery50 or setbattery100 in your terminal.
Check Power Status
To check if your laptop is currently plugged in or running on battery:
cat /sys/class/power_supply/AC/online
Returns:
1= plugged in0= on battery
Hyprland Monitor Configuration
Monitor Setup (monitors.conf)
Omarchy sources monitor settings from ~/.config/hypr/monitors.conf. Example setup for a laptop with an external 1440p display above:
env = GDK_SCALE,1.333334
monitor=eDP-1,preferred,0x0,1
monitor=DP-4,2560x1440,0x-1440,1
monitor=,preferred,auto,1
monitor=eDP-1,preferred,0x0,1— laptop’s built-in display, pinned to position0x0(top-left)monitor=DP-4,2560x1440,0x-1440,1— external monitor positioned above the laptop screenmonitor=,preferred,auto,1— fallback for any other unspecified monitor
Note:
eDP-1is pinned to a fixed position (0x0) instead ofautoto ensure Hyprland always knows where to place it. This prevents workspaces from becoming invisible when monitors are disconnected.
Use hyprctl monitors to list connected monitors and their names.
Auto-Disable Laptop Screen on Lid Close
Instead of permanently disabling the laptop screen with monitor=eDP-1,disable, you can use Hyprland’s bindl to dynamically toggle it based on the lid switch. Add this to ~/.config/hypr/bindings.conf:
# Lid switch: disable laptop screen when closed, re-enable when opened
bindl = , switch:on:Lid Switch, exec, hyprctl dispatch moveworkspacetomonitor active DP-4 && hyprctl keyword monitor "eDP-1,disable"
bindl = , switch:off:Lid Switch, exec, hyprctl keyword monitor "eDP-1,preferred,0x0,1" && hyprctl dispatch moveworkspacetomonitor active eDP-1
How it works:
bindl— a bind that works even when the screen is lockedswitch:on:Lid Switch— triggered when the lid is closedswitch:off:Lid Switch— triggered when the lid is openedhyprctl dispatch moveworkspacetomonitor active <monitor>— moves the current workspace to the target monitor before disabling/enabling, so nothing gets lost or invisiblehyprctl keyword monitor— dynamically changes monitor settings at runtime
Verify your switch name with hyprctl devices — look under the “Switches” section. It’s usually Lid Switch but may differ on some hardware.
Troubleshooting
Bar (e.g. Waybar) not showing on external monitor when lid is closed
Check your Waybar config (~/.config/waybar/config) for a line like "output": "eDP-1". This pins the bar to the laptop screen only, so it disappears when eDP-1 is disabled. Remove that line (or add your external monitor’s name) to let the bar render on any active monitor.
Black screen after disconnecting external monitor
This happens when workspaces that were on the disconnected monitor have no valid monitor to fall back to. The moveworkspacetomonitor commands in the lid bindings above help prevent this. If it still occurs, make sure eDP-1 has a fixed position (0x0) rather than auto in monitors.conf.
Omarchy Config File Hierarchy
Omarchy uses a layered “last wins” approach for Hyprland configuration:
- Defaults (
~/.local/share/omarchy/default/hypr/) — managed by Omarchy, don’t edit directly - Theme (
~/.config/omarchy/current/theme/hyprland.conf) — theme-specific overrides - User (
~/.config/hypr/) — your personal configs, always take precedence
All user customizations go in ~/.config/hypr/ to persist across Omarchy updates.
System Maintenance
Package Cache Cleanup
Regular cleanup of package caches helps free up disk space:
yay -Sc && sudo pacman -Sc
This removes old and uninstalled packages from both AUR (yay) and official repository (pacman) caches.
VPN Configuration
Wireguard VPN Setup
Wireguard is a fast, modern VPN protocol. Here’s how to set it up on Arch:
Installation:
sudo pacman -S wireguard-tools openresolv
Configuration:
sudo cp ~/Documents/VPN-Andrey-Laptop.conf /etc/wireguard/vpn.conf
sudo chmod 600 /etc/wireguard/vpn.conf
Usage:
# Start VPN
sudo wg-quick up vpn
# Check connection status
sudo wg show
# Stop VPN
sudo wg-quick down vpn
Optional DNS resolution update:
sudo resolvconf -u
Xray VLESS+Reality Setup
Xray is a powerful proxy tool that creates an encrypted tunnel to your VPS server, useful for bypassing censorship and improving privacy.
What is Xray?
- Client that connects to your VPS server via encrypted tunnel
- Creates local proxy:
127.0.0.1:10808(SOCKS5) and10809(HTTP) - Traffic flow: Your apps → Local Xray → Encrypted to VPS → Internet
Installation
yay -S xray
sudo mkdir -p /etc/xray
sudo nvim /etc/xray/config.json
Configuration Requirements
Information needed from your server:
- Server IP/domain
- Port (usually 443)
- UUID
- Reality: public key, short ID, SNI domain
Key configuration sections:
- Inbounds: Local SOCKS5 (10808) + HTTP (10809)
- Outbounds: VLESS+Reality to your server + “freedom” for direct
- Routing: Which traffic goes where
Configuration Template
Create /etc/xray/config.json with the following template:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": {
"udp": true
},
"tag": "socks-in"
},
{
"port": 10809,
"listen": "127.0.0.1",
"protocol": "http",
"tag": "http-in"
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "YOUR_SERVER_IP_OR_DOMAIN",
"port": 443,
"users": [
{
"id": "YOUR_UUID",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
"fingerprint": "chrome",
"serverName": "www.microsoft.com",
"publicKey": "YOUR_REALITY_PUBLIC_KEY",
"shortId": "YOUR_SHORT_ID",
"spiderX": ""
}
},
"tag": "proxy"
},
{
"protocol": "freedom",
"tag": "direct"
}
],
"routing": {
"rules": [
{
"type": "field",
"outboundTag": "direct",
"domain": ["geosite:private"]
},
{
"type": "field",
"outboundTag": "proxy",
"network": "tcp,udp"
}
]
}
}
Starting the Service
# Test configuration first
sudo xray run -c /etc/xray/config.json
# If it works, enable as service
sudo systemctl enable xray@config
sudo systemctl start xray@config
# Check status
sudo systemctl status xray@config
# View logs
sudo journalctl -u xray@config -f
Usage Options
1. Browser only (recommended):
- Firefox/LibreWolf → Manual proxy →
127.0.0.1:10808SOCKS5
2. System-wide:
- GNOME/KDE Network Settings → Manual proxy
3. Per-app:
proxychains <command>
4. Terminal sessions:
export all_proxy="socks5://127.0.0.1:10808"
Recommended Browser: LibreWolf
LibreWolf is a privacy-focused Firefox fork that’s perfect for use with proxies:
sudo pacman -S librewolf
Configuration:
- Settings → Network → Manual proxy → SOCKS5
127.0.0.1:10808 - Enable “Proxy DNS when using SOCKS v5”
- Disable WebRTC:
about:config→media.peerconnection.enabled = false
Testing Your Setup
# Check your real IP
curl ifconfig.me
# Check IP through proxy (should show VPS IP)
curl --socks5 127.0.0.1:10808 ifconfig.me
Security Verification
Test for leaks at:
Technical Notes
- Traffic is TLS 1.3 encrypted
- Reality protocol makes traffic appear as HTTPS to legitimate sites
- Datacenter IPs may still trigger some “VPN detected” warnings - this is normal behavior
AI Agent Configuration Management
Centralized configs for AI coding agents (Copilot, Claude Code, Codex), symlinked into projects via GNU stow.
Why?
- AI instructions stay out of project git history
- One private repo, version-controlled
- Update once, applies everywhere
- Share configs between similar projects
Directory Structure
Mirror the target project layout so stow can symlink directly:
~/Work/agents-configs/
├── project-name/
│ ├── AGENTS.md → project root
│ └── .github/
│ ├── copilot-instructions.md → .github/
│ └── skills/ → .github/skills/
│ ├── planning-docs/
│ │ ├── SKILL.md
│ │ └── references/
│ │ └── planning-template.md
│ ├── git-workflow/
│ │ └── SKILL.md
│ ├── laravel-testing/
│ │ └── SKILL.md
│ └── ...
├── another-project/
│ ├── AGENTS.md
│ └── .github/
│ └── ...
└── README.md
What goes where
| File | Purpose | Loaded |
|---|---|---|
AGENTS.md | Critical rules, always-on guardrails | Always |
copilot-instructions.md | Architecture overview, conventions | Always |
.github/skills/*/SKILL.md | Task-specific workflows and knowledge | On demand |
Keep AGENTS.md and copilot-instructions.md short (under ~200 lines total). Move procedural details into skills — they only load when relevant, saving context tokens.
Setup with GNU stow
sudo pacman -S stow # Arch Linux
Stow creates symlinks for each item inside a folder, without overwriting existing files (like .github/workflows/).
# Link everything into your project
cd ~/Work/project-name
stow -d ~/Work/agents-configs -t . project-name
# Remove all symlinks
stow -d ~/Work/agents-configs -t . -D project-name
Verify:
ls -la AGENTS.md .github/copilot-instructions.md .github/skills
# Should show arrows → pointing to agents-configs/
.gitignore
Prevent symlinks from being committed:
# AI agent configs (symlinked from agents-configs repo)
AGENTS.md
.github/copilot-instructions.md
.github/skills/
Or set globally for all projects:
echo -e "AGENTS.md\n.github/copilot-instructions.md\n.github/skills/" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global
Troubleshooting
# Check if something is a symlink
file AGENTS.md
# → "symbolic link to ..." = good
# → "ASCII text" = regular file, not linked
# Broken symlink (shows red in ls)?
ls -la ~/Work/agents-configs/project-name/AGENTS.md # check source exists
stow -d ~/Work/agents-configs -t . -R project-name # restow
# "File exists" error?
# Stow won't overwrite existing files. Remove the conflict first, then restow.
Agent Skills Reference
Skills live in .github/skills/<name>/SKILL.md. Format:
---
name: skill-name
description: What it does and when to use it (max 1024 chars)
---
## Instructions
Detailed steps, examples, code snippets...
Optional subdirectories: references/, scripts/, assets/ — loaded only when the agent references them.
Skills are supported by Copilot (VS Code), Codex, and Claude Code. Personal skills (shared across all projects) go in ~/.copilot/skills/.
Last updated: February 8, 2026