From 81d8ea76c00860866b35677df8b580bb722f72fb Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Mon, 11 Mar 2024 05:03:42 +0000 Subject: [PATCH 1/4] Outline shell customization doc --- 2024-03-10_Shell-Customizations.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 2024-03-10_Shell-Customizations.md diff --git a/2024-03-10_Shell-Customizations.md b/2024-03-10_Shell-Customizations.md new file mode 100644 index 0000000..529bb42 --- /dev/null +++ b/2024-03-10_Shell-Customizations.md @@ -0,0 +1,30 @@ +--- +date: 2024-03-10 +title: Shell Customizations and SSH +tags: + - homelab + - linux + - bash + - development +--- + +Taking a detour from actual deployments, I recently started experimenting with different shell customizations. +Until now, I've just used whatever default shell I have available on a given system, but a recent live stream +from [Lawrence Systems](https://www.youtube.com/@LAWRENCESYSTEMS) mentioned shell customizations and tmux and +let me down this rabbithole. I'll also mention SSH configuration as its something that greatly helps my daily +productivity and is tangentially related to some of my customizations. + +## tmux +- explain usage +- explain ssh integration + +## ssh +- describe key configs +- login config +- describe tmux +- config rsync for tmux support + +## BASH Configuration +- choice of BASH +- bashrc link LTS +- explain PS1/PS2 -- GitLab From 481947861a8d0804a6375f241dbb5bbaee8175a7 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 12 Mar 2024 05:52:53 +0000 Subject: [PATCH 2/4] WIP --- 2024-03-10_Shell-Customizations.md | 123 ++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 10 deletions(-) diff --git a/2024-03-10_Shell-Customizations.md b/2024-03-10_Shell-Customizations.md index 529bb42..5f803ef 100644 --- a/2024-03-10_Shell-Customizations.md +++ b/2024-03-10_Shell-Customizations.md @@ -14,17 +14,120 @@ from [Lawrence Systems](https://www.youtube.com/@LAWRENCESYSTEMS) mentioned shel let me down this rabbithole. I'll also mention SSH configuration as its something that greatly helps my daily productivity and is tangentially related to some of my customizations. -## tmux -- explain usage -- explain ssh integration +## `tmux` +I only recently tried using tmux and I don't know why I went so long without it! The +[tmux wiki](https://github.com/tmux/tmux/wiki) offers a complete explanation of what tmux is and all of the +things it can do; in short, it manages processes and terminals. `tmux` has a pretty steep learning curve, but +it only took me a day to get the hang of a few basic shortcuts; `ctrl`+`b`, or the "prefix key" enables +interacting with `tmux` and then the following commands can be entered: +- `?` - Shows a list of tmux key bindings +- `"` - Splits the window vertically and adds a pane +- `up`/`down` - Navigates between vertical panes; if you hold `ctrl`+`b` then it moves the split up and down +- `d` - Detaches the temux session; easy to remember since `ctrl`+`d` is how you detach an SSH session + +I'm not (yet) using tmux by default for local sessions, but I do have it enabled to run when I SSH into some +systems;his is the primary reason I really like `tmux`. I can ssh into my server from my laptop and start a + command (i.e.a very long rsync process) without worrying about disowning the process before my laptop goes + to sleep; when I ssh back in, perhaps from another computer, I have the same terminal history and the same + process as if I was in the same SSH session from earlier. I will go into more detail in the "ssh" section of + this post, but all I had to do is run `tmux new -A -s ssh_tmux` when I connect to attach a tmux session named + `ssh_tmux`, creating it if it doesn't exist. ## ssh -- describe key configs -- login config -- describe tmux -- config rsync for tmux support +For SSH keys, I have one key pair I use for personal systems and another for work. I won't go into detail about +key management or key rotation and instead focus on SSH configuration. My SSH config simply contains global +config options and includes other configuration files for specific hosts. I find this makes it easier to manage +hosts since I can group hosts in different files. My `~/.ssh/config` looks like: +``` +Include config.d/* +Host * + AddKeysToAgent yes + IdentitiesOnly yes +``` +- `AddKeysToAgent` adds keys to my ssh agent so I don't need to enter a passcode after the first time I use a key +- `IdentitiesOnly` prevents SSH from trying to infer an identity file to use if it isn't specified in SSH config + or explicitly supplied as an argument. + +> You can find descriptions of all the SSH config options in the [BSD manpages](https://man.openbsd.org/ssh_config). + +A couple example hosts look like: +``` +Host work.server + HostName + User ┌──[22:27]─[d_mcknight@MCKNIGHT-FW13]─(~) +$ + + +And a snippet from .bashrc related to that: +```shell + color_off="\[\033[0m\]" # Text Reset + + # Regular Colors + black="\[\033[0;30m\]" + red="\[\033[0;31m\]" + green="\[\033[0;32m\]" + yellow="\[\033[0;33m\]" + blue="\[\033[0;34m\]" + purple="\[\033[0;35m\]" + cyan="\[\033[0;36m\]" + white="\[\033[0;37m\]" + + path_color=$blue + chrome_color=$purple + context_color=$cyan + prompt_symbol=@ # 🚀💲 + prompt='\$' + if [ "$EUID" -eq 0 ]; then # Change prompt colors for root user + context_color=$red + prompt_symbol=💀 + fi + PROMPT_COMMAND='if [[ $? != 0 && $? != 130 ]];then echo "⚠️";fi' + PS1="$chrome_color┌──[${context_color}\A${chrome_color}]─"'${debian_chroot:+('${path_color}'$(realpath $debian_chroot --relative-to $PWD --relative-base /home)'${chrome_color}')─}${VIRTUAL_ENV:+('${path_color}'$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home)'${chrome_color}')─}'"[${context_color}\u${chrome_color}${prompt_symbol}${context_color}\h${chrome_color}]─(${path_color}\w${chrome_color})\n${chrome_color}└${context_color}${prompt}${color_off} " + PS2=$chrome_color'└>$color_off ' + + export VIRTUAL_ENV_DISABLE_PROMPT=1 +``` +There's a lot going on in the prompt, but I will highlight pieces of it; keep in mind that the snippets below may +not be valid on their own and that some of the color formatting may be lost as I cut up the long prompt string. + +`PROMPT_COMMAND='if [[ $? != 0 && $? != 130 ]];then echo "⚠️";fi'` isn't part of the prompt string, but rather an +expression evaluated before the prompt string. This renders a ⚠️ if the previous command fails and isn't just an +empty command. + +`[${context_color}\A${chrome_color}]` prints the current time in 24H format. Helpful if you open a terminal and +want to quickly reference when you ran the last command and when it completed. + +`${debian_chroot:+('${path_color}'$(realpath $debian_chroot --relative-to $PWD --relative-base /home)'${chrome_color}')─}` +and `${VIRTUAL_ENV:+('${path_color}'$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home'${chrome_color}')─})` +print an active chroot or Python venv path if active. I print these relative to the current directory if within `home` \ No newline at end of file -- GitLab From 4440e5f68696f219eef85529f672413f04b73eeb Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Wed, 13 Mar 2024 04:18:50 +0000 Subject: [PATCH 3/4] Finish post --- 2024-03-10_Shell-Customizations.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/2024-03-10_Shell-Customizations.md b/2024-03-10_Shell-Customizations.md index 5f803ef..41a0ae3 100644 --- a/2024-03-10_Shell-Customizations.md +++ b/2024-03-10_Shell-Customizations.md @@ -113,7 +113,7 @@ And a snippet from .bashrc related to that: prompt_symbol=💀 fi PROMPT_COMMAND='if [[ $? != 0 && $? != 130 ]];then echo "⚠️";fi' - PS1="$chrome_color┌──[${context_color}\A${chrome_color}]─"'${debian_chroot:+('${path_color}'$(realpath $debian_chroot --relative-to $PWD --relative-base /home)'${chrome_color}')─}${VIRTUAL_ENV:+('${path_color}'$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home)'${chrome_color}')─}'"[${context_color}\u${chrome_color}${prompt_symbol}${context_color}\h${chrome_color}]─(${path_color}\w${chrome_color})\n${chrome_color}└${context_color}${prompt}${color_off} " + PS1="$chrome_color┌──[${context_color}\A${chrome_color}]─"'${debian_chroot:+('${path_color}'$debian_chroot'${chrome_color}')─}${VIRTUAL_ENV:+('${path_color}'$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home)'${chrome_color}')─}'"[${context_color}\u${chrome_color}${prompt_symbol}${context_color}\h${chrome_color}]─(${path_color}\w${chrome_color})\n${chrome_color}└${context_color}${prompt}${color_off} " PS2=$chrome_color'└>$color_off ' export VIRTUAL_ENV_DISABLE_PROMPT=1 @@ -128,6 +128,27 @@ empty command. `[${context_color}\A${chrome_color}]` prints the current time in 24H format. Helpful if you open a terminal and want to quickly reference when you ran the last command and when it completed. -`${debian_chroot:+('${path_color}'$(realpath $debian_chroot --relative-to $PWD --relative-base /home)'${chrome_color}')─}` +`${debian_chroot:+('${path_color}'$debian_chroot'${chrome_color}')─}` and `${VIRTUAL_ENV:+('${path_color}'$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home'${chrome_color}')─})` -print an active chroot or Python venv path if active. I print these relative to the current directory if within `home` \ No newline at end of file +print an active chroot or Python venv path, if active. I print the venv path relative to the current directory +if within `home`; I find this helpful when I have multiple projects to make sure I know which one I'm looking at. +Note that I also specify `export VIRTUAL_ENV_DISABLE_PROMPT=1` to suppress the default `(venv)` prompt prefix. + +`[${context_color}\u${chrome_color}${prompt_symbol}${context_color}\h${chrome_color}]` looks like the default shell, +`user@hostname` except when root the `@` is replaced with `💀` as an extra visual reminder that its a root shell. + +`(${path_color}\w${chrome_color})` shows the current shell path like the default shell + +`\n${chrome_color}└${context_color}${prompt}${color_off} ` continues to the next line and inserts the `$` or `#` +prompt, followed by a space. + + +`PS2=$chrome_color'└>$color_off '` updates the prefix used when there's a newline in a command. I like that this +makes each line start vertically aligned and it keeps the chrome colored differently from the inputs. + + +## Further Reading +SSH, BASH, and tmux are all over a decade old with plenty of good documentation and write-ups that I've referenced. +My current `.bashrc` is in [this gist](https://gist.github.com/d-mcknight/176899ca924b5b4cfdf7692e36ca568e) and +I will try to keep that updated as I make changes; maybe one day I'll promote it to an actual repository with other +config files. -- GitLab From c4714d0afc1a73c37f106488b3714ef4f44d61f4 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Thu, 28 Mar 2024 03:33:15 +0000 Subject: [PATCH 4/4] Proofread and minor updates --- 2024-03-10_Shell-Customizations.md | 39 ++++++++++++++---------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/2024-03-10_Shell-Customizations.md b/2024-03-10_Shell-Customizations.md index 41a0ae3..e250785 100644 --- a/2024-03-10_Shell-Customizations.md +++ b/2024-03-10_Shell-Customizations.md @@ -1,5 +1,5 @@ --- -date: 2024-03-10 +date: 2024-03-27 title: Shell Customizations and SSH tags: - homelab @@ -11,31 +11,31 @@ tags: Taking a detour from actual deployments, I recently started experimenting with different shell customizations. Until now, I've just used whatever default shell I have available on a given system, but a recent live stream from [Lawrence Systems](https://www.youtube.com/@LAWRENCESYSTEMS) mentioned shell customizations and tmux and -let me down this rabbithole. I'll also mention SSH configuration as its something that greatly helps my daily +lead me down this rabbithole. I'll also mention SSH configuration as its something that greatly helps my daily productivity and is tangentially related to some of my customizations. -## `tmux` +## tmux I only recently tried using tmux and I don't know why I went so long without it! The [tmux wiki](https://github.com/tmux/tmux/wiki) offers a complete explanation of what tmux is and all of the things it can do; in short, it manages processes and terminals. `tmux` has a pretty steep learning curve, but it only took me a day to get the hang of a few basic shortcuts; `ctrl`+`b`, or the "prefix key" enables -interacting with `tmux` and then the following commands can be entered: +interacting with `tmux` and then a command can be issued. Some of the commands I find most useful are: - `?` - Shows a list of tmux key bindings - `"` - Splits the window vertically and adds a pane - `up`/`down` - Navigates between vertical panes; if you hold `ctrl`+`b` then it moves the split up and down - `d` - Detaches the temux session; easy to remember since `ctrl`+`d` is how you detach an SSH session I'm not (yet) using tmux by default for local sessions, but I do have it enabled to run when I SSH into some -systems;his is the primary reason I really like `tmux`. I can ssh into my server from my laptop and start a +systems; this is the primary reason I really like `tmux`. I can ssh into my server from my laptop and start a command (i.e.a very long rsync process) without worrying about disowning the process before my laptop goes to sleep; when I ssh back in, perhaps from another computer, I have the same terminal history and the same - process as if I was in the same SSH session from earlier. I will go into more detail in the "ssh" section of - this post, but all I had to do is run `tmux new -A -s ssh_tmux` when I connect to attach a tmux session named - `ssh_tmux`, creating it if it doesn't exist. + process attached. I will go into more detail in the "ssh" section of this post, but all I had to do is run + `tmux new -A -s ssh_tmux` when I connect to attach a tmux session named `ssh_tmux`, creating it if it doesn't + exist. ## ssh For SSH keys, I have one key pair I use for personal systems and another for work. I won't go into detail about -key management or key rotation and instead focus on SSH configuration. My SSH config simply contains global +key management or key rotation and instead will focus on SSH configuration. My SSH config simply contains global config options and includes other configuration files for specific hosts. I find this makes it easier to manage hosts since I can group hosts in different files. My `~/.ssh/config` looks like: ``` @@ -73,14 +73,13 @@ Host mcknight.unraid why this is necessary, but it solved a problem. -To work around rsync, I aliased the command in my `.bashrc`: `alias rsync="rsync -e 'ssh -o RemoteCommand=none'"`. +To work around rsync issues, I aliased the command in my `.bashrc`: `alias rsync="rsync -e 'ssh -o RemoteCommand=none'"`. This might cause some problems with fully local transfers, but I don't alias this on servers where I would move enough data around to necessitate using rsync. ## BASH Configuration I use `bash` primarily since its available in pretty much every Linux distro, Windows, and MacOS (not that I use -MacOS). I haven't had any motivation to explore zsh or ksh so I can't justify any reason to choose one over the -other. I mostly use a standard `.bashrc` that ships with Mint, but I recently updated the PS1 and PS2 variables +MacOS). I mostly use a standard `.bashrc` that ships with Mint, but I recently updated the PS1 and PS2 variables using [Tom from Lawrence Systems'](https://github.com/lawrencesystems/dotfiles/blob/master/.bash_profile) as inspiration. @@ -121,32 +120,30 @@ And a snippet from .bashrc related to that: There's a lot going on in the prompt, but I will highlight pieces of it; keep in mind that the snippets below may not be valid on their own and that some of the color formatting may be lost as I cut up the long prompt string. -`PROMPT_COMMAND='if [[ $? != 0 && $? != 130 ]];then echo "⚠️";fi'` isn't part of the prompt string, but rather an +- `PROMPT_COMMAND='if [[ $? != 0 && $? != 130 ]];then echo "⚠️";fi'` isn't part of the prompt string, but rather an expression evaluated before the prompt string. This renders a ⚠️ if the previous command fails and isn't just an empty command. -`[${context_color}\A${chrome_color}]` prints the current time in 24H format. Helpful if you open a terminal and +- `[${context_color}\A${chrome_color}]` prints the current time in 24H format. Helpful if you open a terminal and want to quickly reference when you ran the last command and when it completed. -`${debian_chroot:+('${path_color}'$debian_chroot'${chrome_color}')─}` +- `${debian_chroot:+('${path_color}'$debian_chroot'${chrome_color}')─}` and `${VIRTUAL_ENV:+('${path_color}'$(realpath $VIRTUAL_ENV --relative-to $PWD --relative-base /home'${chrome_color}')─})` print an active chroot or Python venv path, if active. I print the venv path relative to the current directory if within `home`; I find this helpful when I have multiple projects to make sure I know which one I'm looking at. Note that I also specify `export VIRTUAL_ENV_DISABLE_PROMPT=1` to suppress the default `(venv)` prompt prefix. -`[${context_color}\u${chrome_color}${prompt_symbol}${context_color}\h${chrome_color}]` looks like the default shell, +- `[${context_color}\u${chrome_color}${prompt_symbol}${context_color}\h${chrome_color}]` looks like the default shell, `user@hostname` except when root the `@` is replaced with `💀` as an extra visual reminder that its a root shell. -`(${path_color}\w${chrome_color})` shows the current shell path like the default shell +- `(${path_color}\w${chrome_color})` shows the current shell path like the default shell -`\n${chrome_color}└${context_color}${prompt}${color_off} ` continues to the next line and inserts the `$` or `#` +- `\n${chrome_color}└${context_color}${prompt}${color_off} ` continues to the next line and inserts the `$` or `#` prompt, followed by a space. - -`PS2=$chrome_color'└>$color_off '` updates the prefix used when there's a newline in a command. I like that this +- `PS2=$chrome_color'└>$color_off '` updates the prefix used when there's a newline in a command. I like that this makes each line start vertically aligned and it keeps the chrome colored differently from the inputs. - ## Further Reading SSH, BASH, and tmux are all over a decade old with plenty of good documentation and write-ups that I've referenced. My current `.bashrc` is in [this gist](https://gist.github.com/d-mcknight/176899ca924b5b4cfdf7692e36ca568e) and -- GitLab