who even cares about fedora
This commit is contained in:
parent
fbc558877c
commit
35571c4c44
140
README.md
140
README.md
@ -4,20 +4,18 @@
|
||||
<br>
|
||||
</div>
|
||||
|
||||
Secure Fedora Server setup with LUKS encryption, TPM, and BTRFS RAID1 for (Hetzner) Dedicated Servers.
|
||||
|
||||
> [!NOTE]
|
||||
> This project is still WIP, having some issues with networking of the installeer / installed instance.
|
||||
Secure AlmaLinux Server setup with LUKS encryption, TPM, and mdadm RAID1 for Hetzner Dedicated Servers.
|
||||
|
||||
## Features
|
||||
|
||||
- Fedora Server base
|
||||
- Full disk encryption with LUKS
|
||||
- AlmaLinux Server base
|
||||
- Full disk encryption with LUKS (native Hetzner support)
|
||||
- Remote unlock via Tang server
|
||||
- TPM-based boot verification
|
||||
- BTRFS RAID1 for data redundancy
|
||||
- Dedicated database subvolume with `nodatacow` and `noatime`
|
||||
- mdadm RAID1 + XFS (RHEL standard)
|
||||
- SSH key-only access with early boot SSH via dropbear
|
||||
- Automated provisioning using Hetzner installimage
|
||||
- Modern development environment with dotfiles
|
||||
|
||||
If you need a dead man's switch to go along with it check out [raven](https://git.dominik-roth.eu/dodox/raven).
|
||||
|
||||
@ -34,68 +32,86 @@ The system uses multiple methods to unlock the LUKS volumes:
|
||||
- Uses dropbear for early SSH access
|
||||
- Can be used for recovery or maintenance
|
||||
|
||||
### TPM Updates
|
||||
After firmware updates (UEFI/BIOS), the TPM bindings need to be updated:
|
||||
(otherwise the system will not be able to boot without recovery phrase)
|
||||
1. Use the provided script: `sudo /root/update-tpm-bindings.py`
|
||||
2. The script will:
|
||||
- Show current PCR values
|
||||
- Update TPM bindings to match new measurements
|
||||
- Verify all bindings are correct
|
||||
3. Manual passphrase is available in `/root/luks-passphrase.txt` if needed
|
||||
### Unlock Strategy
|
||||
The system supports multiple unlock methods:
|
||||
1. **Manual unlock via SSH** (default):
|
||||
- SSH to server on port 22 (dropbear in early boot)
|
||||
- Enter LUKS passphrase when prompted (twice, once per disk)
|
||||
- System continues normal boot
|
||||
2. **Automatic unlock** (optional):
|
||||
- Configure TPM2 and/or Tang servers in post-install.sh
|
||||
- System unlocks automatically if conditions are met
|
||||
- Falls back to manual unlock if automatic fails
|
||||
|
||||
## Setup
|
||||
## Quick Install
|
||||
|
||||
1. **Configure Installer**
|
||||
Boot your Hetzner server into rescue mode and run:
|
||||
|
||||
```bash
|
||||
wget -qO- https://git.dominik-roth.eu/dodox/nullpoint/raw/branch/master/install.sh | bash
|
||||
```
|
||||
|
||||
The installer will:
|
||||
- Detect your SSH key from the current session
|
||||
- Ask for hostname and username
|
||||
- Generate a secure LUKS passphrase (SAVE IT!)
|
||||
- Download and configure everything
|
||||
- Run Hetzner's installimage automatically
|
||||
|
||||
## Manual Setup
|
||||
|
||||
If you prefer to configure manually:
|
||||
|
||||
1. **Boot into Hetzner Rescue Mode**
|
||||
- Log into Hetzner Robot
|
||||
- Select your server → Rescue tab
|
||||
- Choose "Linux 64 bit" and activate
|
||||
- SSH into rescue system
|
||||
|
||||
2. **Download Configuration**
|
||||
```bash
|
||||
# Edit the variables at the top of install.sh:
|
||||
vim install.sh
|
||||
git clone https://git.dominik-roth.eu/dodox/nullpoint.git
|
||||
cd nullpoint
|
||||
```
|
||||
Set your:
|
||||
- Tang server URLs and thumbprints
|
||||
- TPM PCR settings
|
||||
- Fedora version
|
||||
- SSH public key for the default user
|
||||
|
||||
2. **Install on Hetzner Server**
|
||||
- Log into Hetzner Robot
|
||||
- Select your server
|
||||
- Go to "Rescue" tab
|
||||
- Choose "Linux" and "64 bit"
|
||||
- Activate Rescue System
|
||||
- Upload the installer:
|
||||
```bash
|
||||
scp install.sh root@your-server:/root/
|
||||
```
|
||||
- SSH into Rescue System:
|
||||
```bash
|
||||
ssh root@your-server
|
||||
```
|
||||
- Make it executable and run:
|
||||
```bash
|
||||
chmod +x install.sh
|
||||
./install.sh
|
||||
```
|
||||
- If the script tells you that no TPM is available, you'll need to make a support ticket to get KVM access and enable TPM in the BIOS.
|
||||
- The script will:
|
||||
- Generate and display a LUKS passphrase (save this!)
|
||||
- Download and prepare the Fedora installer
|
||||
- Configure networking for Hetzner's unusual setup
|
||||
- Start the Fedora installer
|
||||
- You can monitor the installation via SSH on port 2222:
|
||||
```bash
|
||||
ssh -p 2222 root@your-server
|
||||
```
|
||||
- During the Fedora installation:
|
||||
- Disk encryption and RAID will be configured
|
||||
- TPM and Tang bindings will be set up
|
||||
- Network configuration will be applied
|
||||
3. **Configure**
|
||||
- Edit `install.conf` and change `CRYPTPASSWORD`
|
||||
- Edit `post-install.sh` and set your SSH key (REQUIRED!)
|
||||
- Optionally configure Tang servers and TPM settings
|
||||
|
||||
3. **Verify Installation**
|
||||
4. **Install**
|
||||
```bash
|
||||
installimage -a -c install.conf -s post-install.sh
|
||||
```
|
||||
|
||||
## What Gets Installed
|
||||
|
||||
Hetzner installimage will:
|
||||
- Set up mdadm RAID1 across both drives
|
||||
- Create LUKS encryption with your passphrase
|
||||
- Install AlmaLinux with XFS filesystem
|
||||
- Single root partition (no LVM complexity)
|
||||
|
||||
post-install.sh will configure:
|
||||
- User account with SSH key and zsh shell
|
||||
- oh-my-zsh with powerlevel10k theme
|
||||
- Dotfiles (zsh, tmux, p10k configs)
|
||||
- Clevis for TPM/Tang unlock (if configured)
|
||||
- Dropbear for remote unlock
|
||||
- Modern CLI tools (lsd, bat, neovim)
|
||||
- Security hardening (SELinux, SSH)
|
||||
|
||||
## Post-Installation
|
||||
|
||||
1. **First Boot**
|
||||
- Enter LUKS passphrase twice (once per disk)
|
||||
- System will boot into AlmaLinux
|
||||
|
||||
2. **Verify Installation**
|
||||
```bash
|
||||
ssh null@your-server
|
||||
systemctl status clevis-luks-askpass
|
||||
lsblk
|
||||
btrfs filesystem show # Check RAID1 status
|
||||
clevis-luks-list -d /dev/sda3 # Note: sda3 is the LUKS partition
|
||||
cat /proc/mdstat # Check RAID1 status
|
||||
df -h # Check filesystem
|
||||
```
|
271
dotfiles/.p10k.zsh
Normal file
271
dotfiles/.p10k.zsh
Normal file
@ -0,0 +1,271 @@
|
||||
'builtin' 'local' '-a' 'p10k_config_opts'
|
||||
[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases')
|
||||
[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob')
|
||||
[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand')
|
||||
'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand'
|
||||
() {
|
||||
emulate -L zsh
|
||||
setopt no_unset extended_glob
|
||||
unset -m 'POWERLEVEL9K_*'
|
||||
autoload -Uz is-at-least && is-at-least 5.1 || return
|
||||
zmodload zsh/langinfo
|
||||
if [[ ${langinfo[CODESET]:-} != (utf|UTF)(-|)8 ]]; then
|
||||
local LC_ALL=${${(@M)$(locale -a):#*.(utf|UTF)(-|)8}[1]:-en_US.UTF-8}
|
||||
fi
|
||||
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
|
||||
context
|
||||
dir
|
||||
vcs
|
||||
)
|
||||
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
|
||||
background_jobs
|
||||
direnv
|
||||
virtualenv
|
||||
pyenv
|
||||
disk_usage
|
||||
)
|
||||
typeset -g POWERLEVEL9K_VISUAL_IDENTIFIER_EXPANSION='${P9K_VISUAL_IDENTIFIER// }'
|
||||
typeset -g POWERLEVEL9K_MODE=nerdfont-complete
|
||||
typeset -g POWERLEVEL9K_ICON_BEFORE_CONTENT=
|
||||
typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false
|
||||
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX='%242F╭─'
|
||||
typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_PREFIX='%242F├─'
|
||||
typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX='%242F╰─'
|
||||
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_SUFFIX='%242F─╮'
|
||||
typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_SUFFIX='%242F─┤'
|
||||
typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_SUFFIX='%242F─╯'
|
||||
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' '
|
||||
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_BACKGROUND=
|
||||
if [[ $POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR != ' ' ]]; then
|
||||
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_FOREGROUND=242
|
||||
typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_FIRST_SEGMENT_END_SYMBOL='%{%}'
|
||||
typeset -g POWERLEVEL9K_EMPTY_LINE_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='%{%}'
|
||||
fi
|
||||
typeset -g POWERLEVEL9K_LEFT_SUBSEGMENT_SEPARATOR='\uE0B1'
|
||||
typeset -g POWERLEVEL9K_RIGHT_SUBSEGMENT_SEPARATOR='\uE0B3'
|
||||
typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR='\uE0B0'
|
||||
typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR='\uE0B2'
|
||||
typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL='\uE0B0'
|
||||
typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='\uE0B2'
|
||||
typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL=''
|
||||
typeset -g POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL=''
|
||||
typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=
|
||||
typeset -g POWERLEVEL9K_OS_ICON_FOREGROUND=232
|
||||
typeset -g POWERLEVEL9K_OS_ICON_BACKGROUND=7
|
||||
typeset -g POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION='%B${P9K_CONTENT// }'
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_BACKGROUND=
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=76
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=196
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION=' '
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION=' '
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION=' '
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIOWR_CONTENT_EXPANSION=' '
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=true
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL=
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_{LEFT,RIGHT}_WHITESPACE=
|
||||
typeset -g POWERLEVEL9K_DIR_BACKGROUND=234
|
||||
typeset -g POWERLEVEL9K_DIR_FOREGROUND=39
|
||||
typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique
|
||||
typeset -g POWERLEVEL9K_SHORTEN_DELIMITER=
|
||||
typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=103
|
||||
typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=39
|
||||
typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=false
|
||||
local anchor_files=(
|
||||
.bzr
|
||||
.citc
|
||||
.git
|
||||
.hg
|
||||
.node-version
|
||||
.python-version
|
||||
.ruby-version
|
||||
.shorten_folder_marker
|
||||
.svn
|
||||
.terraform
|
||||
CVS
|
||||
Cargo.toml
|
||||
composer.json
|
||||
go.mod
|
||||
package.json
|
||||
)
|
||||
typeset -g POWERLEVEL9K_SHORTEN_FOLDER_MARKER="(${(j:|:)anchor_files})"
|
||||
typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=1
|
||||
typeset -g POWERLEVEL9K_DIR_MAX_LENGTH=80
|
||||
typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS=40
|
||||
typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT=50
|
||||
typeset -g POWERLEVEL9K_DIR_HYPERLINK=false
|
||||
typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=true
|
||||
typeset -g POWERLEVEL9K_DIR_CLASSES=()
|
||||
typeset -g POWERLEVEL9K_VCS_CLEAN_FOREGROUND=10
|
||||
typeset -g POWERLEVEL9K_VCS_CLEAN_BACKGROUND=235
|
||||
typeset -g POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=10
|
||||
typeset -g POWERLEVEL9K_VCS_MODIFIED_BACKGROUND=235
|
||||
typeset -g POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=10
|
||||
typeset -g POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND=235
|
||||
typeset -g POWERLEVEL9K_VCS_CONFLICTED_FOREGROUND=9
|
||||
typeset -g POWERLEVEL9K_VCS_CONFLICTED_BACKGROUND=235
|
||||
typeset -g POWERLEVEL9K_VCS_LOADING_FOREGROUND=15
|
||||
typeset -g POWERLEVEL9K_VCS_LOADING_BACKGROUND=255
|
||||
typeset -g POWERLEVEL9K_VCS_BRANCH_ICON='\uF126 '
|
||||
POWERLEVEL9K_VCS_BRANCH_ICON=${(g::)POWERLEVEL9K_VCS_BRANCH_ICON}
|
||||
typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?'
|
||||
POWERLEVEL9K_VCS_UNTRACKED_ICON=${(g::)POWERLEVEL9K_VCS_UNTRACKED_ICON}
|
||||
function my_git_formatter() {
|
||||
emulate -L zsh
|
||||
if [[ -n $P9K_CONTENT ]]; then
|
||||
typeset -g my_git_format=$P9K_CONTENT
|
||||
return
|
||||
fi
|
||||
local meta=''
|
||||
local clean=''
|
||||
local modified=''
|
||||
local untracked=''
|
||||
local conflicted=''
|
||||
local res
|
||||
local where
|
||||
if [[ -n $VCS_STATUS_LOCAL_BRANCH ]]; then
|
||||
res+="${clean}${POWERLEVEL9K_VCS_BRANCH_ICON}"
|
||||
where=${(V)VCS_STATUS_LOCAL_BRANCH}
|
||||
elif [[ -n $VCS_STATUS_TAG ]]; then
|
||||
res+="${meta}#"
|
||||
where=${(V)VCS_STATUS_TAG}
|
||||
fi
|
||||
(( $#where > 32 )) && where[13,-13]="…"
|
||||
res+="${clean}${where//\%/%%}"
|
||||
[[ -z $where ]] && res+="${meta}@${clean}${VCS_STATUS_COMMIT[1,8]}"
|
||||
if [[ -n ${VCS_STATUS_REMOTE_BRANCH:#$VCS_STATUS_LOCAL_BRANCH} ]]; then
|
||||
res+="${meta}:${clean}${(V)VCS_STATUS_REMOTE_BRANCH//\%/%%}"
|
||||
fi
|
||||
(( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}⇣${VCS_STATUS_COMMITS_BEHIND}"
|
||||
(( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" "
|
||||
(( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}⇡${VCS_STATUS_COMMITS_AHEAD}"
|
||||
(( VCS_STATUS_STASHES )) && res+=" ${clean}*${VCS_STATUS_STASHES}"
|
||||
[[ -n $VCS_STATUS_ACTION ]] && res+=" ${conflicted}${VCS_STATUS_ACTION}"
|
||||
(( VCS_STATUS_NUM_CONFLICTED )) && res+=" ${conflicted}~${VCS_STATUS_NUM_CONFLICTED}"
|
||||
(( VCS_STATUS_NUM_STAGED )) && res+=" ${modified}+${VCS_STATUS_NUM_STAGED}"
|
||||
(( VCS_STATUS_NUM_UNSTAGED )) && res+=" ${modified}!${VCS_STATUS_NUM_UNSTAGED}"
|
||||
(( VCS_STATUS_NUM_UNTRACKED )) && res+=" ${untracked}${POWERLEVEL9K_VCS_UNTRACKED_ICON}${VCS_STATUS_NUM_UNTRACKED}"
|
||||
typeset -g my_git_format=$res
|
||||
}
|
||||
functions -M my_git_formatter 2>/dev/null
|
||||
typeset -g POWERLEVEL9K_VCS_DISABLE_GITSTATUS_FORMATTING=true
|
||||
typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${$((my_git_formatter()))+${my_git_format}}'
|
||||
typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED,COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=-1
|
||||
typeset -g POWERLEVEL9K_VCS_BACKENDS=(git)
|
||||
typeset -g POWERLEVEL9K_STATUS_EXTENDED_STATES=true
|
||||
typeset -g POWERLEVEL9K_STATUS_OK=true
|
||||
typeset -g POWERLEVEL9K_STATUS_OK_VISUAL_IDENTIFIER_EXPANSION='✔'
|
||||
typeset -g POWERLEVEL9K_STATUS_OK_PIPE=true
|
||||
typeset -g POWERLEVEL9K_STATUS_OK_PIPE_VISUAL_IDENTIFIER_EXPANSION='✔'
|
||||
typeset -g POWERLEVEL9K_STATUS_ERROR=true
|
||||
typeset -g POWERLEVEL9K_STATUS_ERROR_VISUAL_IDENTIFIER_EXPANSION='✘'
|
||||
typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL=true
|
||||
typeset -g POWERLEVEL9K_STATUS_VERBOSE_SIGNAME=false
|
||||
typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_VISUAL_IDENTIFIER_EXPANSION='✘'
|
||||
typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE=true
|
||||
typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_VISUAL_IDENTIFIER_EXPANSION='✘'
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=0
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_BACKGROUND=3
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s'
|
||||
typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VERBOSE=false
|
||||
typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_CONTENT_EXPANSION=
|
||||
typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_VISUAL_IDENTIFIER_EXPANSION=
|
||||
typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL=95
|
||||
typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_LEVEL=98
|
||||
typeset -g POWERLEVEL9K_DISK_USAGE_ONLY_WARNING=true
|
||||
typeset -g POWERLEVEL9K_VI_MODE_FOREGROUND=0
|
||||
typeset -g POWERLEVEL9K_VI_COMMAND_MODE_STRING=NORMAL
|
||||
typeset -g POWERLEVEL9K_VI_MODE_NORMAL_BACKGROUND=2
|
||||
typeset -g POWERLEVEL9K_VI_VISUAL_MODE_STRING=VISUAL
|
||||
typeset -g POWERLEVEL9K_VI_MODE_VISUAL_BACKGROUND=4
|
||||
typeset -g POWERLEVEL9K_VI_OVERWRITE_MODE_STRING=OVERTYPE
|
||||
typeset -g POWERLEVEL9K_VI_MODE_OVERWRITE_BACKGROUND=3
|
||||
typeset -g POWERLEVEL9K_VI_INSERT_MODE_STRING=
|
||||
typeset -g POWERLEVEL9K_VI_MODE_INSERT_FOREGROUND=8
|
||||
typeset -g POWERLEVEL9K_LOAD_WHICH=5
|
||||
typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_TOTAL=true
|
||||
typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_FILTERED=false
|
||||
typeset -g POWERLEVEL9K_TIMEWARRIOR_CONTENT_EXPANSION='${P9K_CONTENT:0:24}${${P9K_CONTENT:24}:+…}'
|
||||
typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND=1
|
||||
typeset -g POWERLEVEL9K_CONTEXT_ROOT_BACKGROUND=0
|
||||
typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND=3
|
||||
typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_BACKGROUND=0
|
||||
typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND=3
|
||||
typeset -g POWERLEVEL9K_CONTEXT_BACKGROUND=0
|
||||
typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE='%n@%m'
|
||||
typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_TEMPLATE='%n@%m'
|
||||
typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE='%n'
|
||||
typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false
|
||||
typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER=
|
||||
typeset -g POWERLEVEL9K_ANACONDA_SHOW_PYTHON_VERSION=false
|
||||
typeset -g POWERLEVEL9K_ANACONDA_{LEFT,RIGHT}_DELIMITER=
|
||||
typeset -g POWERLEVEL9K_PYENV_SOURCES=(shell local global)
|
||||
typeset -g POWERLEVEL9K_PYENV_PROMPT_ALWAYS_SHOW=false
|
||||
typeset -g POWERLEVEL9K_GOENV_SOURCES=(shell local global)
|
||||
typeset -g POWERLEVEL9K_GOENV_PROMPT_ALWAYS_SHOW=false
|
||||
typeset -g POWERLEVEL9K_NODENV_PROMPT_ALWAYS_SHOW=false
|
||||
typeset -g POWERLEVEL9K_NODEENV_SHOW_NODE_VERSION=false
|
||||
typeset -g POWERLEVEL9K_NODEENV_{LEFT,RIGHT}_DELIMITER=
|
||||
typeset -g POWERLEVEL9K_NODE_VERSION_PROJECT_ONLY=true
|
||||
typeset -g POWERLEVEL9K_GO_VERSION_PROJECT_ONLY=true
|
||||
typeset -g POWERLEVEL9K_RUST_VERSION_PROJECT_ONLY=true
|
||||
typeset -g POWERLEVEL9K_DOTNET_VERSION_PROJECT_ONLY=true
|
||||
typeset -g POWERLEVEL9K_RBENV_SOURCES=(shell local global)
|
||||
typeset -g POWERLEVEL9K_RBENV_PROMPT_ALWAYS_SHOW=false
|
||||
typeset -g POWERLEVEL9K_RVM_SHOW_GEMSET=false
|
||||
typeset -g POWERLEVEL9K_RVM_SHOW_PREFIX=false
|
||||
typeset -g POWERLEVEL9K_LUAENV_SOURCES=(shell local global)
|
||||
typeset -g POWERLEVEL9K_LUAENV_PROMPT_ALWAYS_SHOW=false
|
||||
typeset -g POWERLEVEL9K_JENV_SOURCES=(shell local global)
|
||||
typeset -g POWERLEVEL9K_JENV_PROMPT_ALWAYS_SHOW=false
|
||||
typeset -g POWERLEVEL9K_PLENV_SOURCES=(shell local global)
|
||||
typeset -g POWERLEVEL9K_PLENV_PROMPT_ALWAYS_SHOW=false
|
||||
typeset -g POWERLEVEL9K_TERRAFORM_CLASSES=(
|
||||
'*' DEFAULT)
|
||||
typeset -g POWERLEVEL9K_TERRAFORM_DEFAULT_FOREGROUND=4
|
||||
typeset -g POWERLEVEL9K_TERRAFORM_DEFAULT_BACKGROUND=0
|
||||
typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc'
|
||||
typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=(
|
||||
'*' DEFAULT)
|
||||
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND=7
|
||||
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_BACKGROUND=5
|
||||
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION=
|
||||
POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${P9K_KUBECONTEXT_CLOUD_CLUSTER:-${P9K_KUBECONTEXT_NAME}}'
|
||||
POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${${:-/$P9K_KUBECONTEXT_NAMESPACE}:#/default}'
|
||||
typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|terraform|pulumi'
|
||||
typeset -g POWERLEVEL9K_AWS_CLASSES=(
|
||||
'*' DEFAULT)
|
||||
typeset -g POWERLEVEL9K_AZURE_SHOW_ON_COMMAND='az|terraform|pulumi'
|
||||
typeset -g POWERLEVEL9K_GCLOUD_SHOW_ON_COMMAND='gcloud|gcs'
|
||||
typeset -g POWERLEVEL9K_GCLOUD_CONTENT_EXPANSION='${P9K_GCLOUD_PROJECT//\%/%%}'
|
||||
typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_SHOW_ON_COMMAND='terraform|pulumi'
|
||||
typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES=(
|
||||
'*' DEFAULT)
|
||||
typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_CONTENT_EXPANSION='${P9K_GOOGLE_APP_CRED_PROJECT_ID//\%/%%}'
|
||||
typeset -g POWERLEVEL9K_VPN_IP_FOREGROUND=0
|
||||
typeset -g POWERLEVEL9K_VPN_IP_BACKGROUND=6
|
||||
typeset -g POWERLEVEL9K_VPN_IP_CONTENT_EXPANSION=
|
||||
typeset -g POWERLEVEL9K_VPN_IP_INTERFACE='(wg|(.*tun))[0-9]*'
|
||||
typeset -g POWERLEVEL9K_BATTERY_LOW_THRESHOLD=20
|
||||
typeset -g POWERLEVEL9K_BATTERY_LOW_FOREGROUND=1
|
||||
typeset -g POWERLEVEL9K_BATTERY_{CHARGING,CHARGED}_FOREGROUND=2
|
||||
typeset -g POWERLEVEL9K_BATTERY_DISCONNECTED_FOREGROUND=3
|
||||
typeset -g POWERLEVEL9K_BATTERY_STAGES=$'\uf58d\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf578'
|
||||
typeset -g POWERLEVEL9K_BATTERY_VERBOSE=false
|
||||
typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}'
|
||||
typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false
|
||||
function prompt_example() {
|
||||
p10k segment -i "POWERLEVEL9K_LINUX_ICON" -r -f blue -t " "
|
||||
}
|
||||
function instant_prompt_example() {
|
||||
prompt_example
|
||||
}
|
||||
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off
|
||||
typeset -g POWERLEVEL9K_INSTANT_PROMPT=verbose
|
||||
typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true
|
||||
(( ! $+functions[p10k] )) || p10k reload
|
||||
}
|
||||
(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]}
|
||||
'builtin' 'unset' 'p10k_config_opts'
|
1370
dotfiles/.tmux.conf
Normal file
1370
dotfiles/.tmux.conf
Normal file
File diff suppressed because it is too large
Load Diff
404
dotfiles/.tmux.conf.local
Normal file
404
dotfiles/.tmux.conf.local
Normal file
@ -0,0 +1,404 @@
|
||||
# : << EOF
|
||||
# https://github.com/gpakosz/.tmux
|
||||
# (‑●‑●)> dual licensed under the WTFPL v2 license and the MIT license,
|
||||
# without any warranty.
|
||||
# Copyright 2012— Gregory Pakosz (@gpakosz).
|
||||
|
||||
|
||||
# -- navigation ----------------------------------------------------------------
|
||||
|
||||
# if you're running tmux within iTerm2
|
||||
# - and tmux is 1.9 or 1.9a
|
||||
# - and iTerm2 is configured to let option key act as +Esc
|
||||
# - and iTerm2 is configured to send [1;9A -> [1;9D for option + arrow keys
|
||||
# then uncomment the following line to make Meta + arrow keys mapping work
|
||||
#set -ga terminal-overrides "*:kUP3=\e[1;9A,*:kDN3=\e[1;9B,*:kRIT3=\e[1;9C,*:kLFT3=\e[1;9D"
|
||||
|
||||
|
||||
# -- windows & pane creation ---------------------------------------------------
|
||||
|
||||
# new window retains current path, possible values are:
|
||||
# - true
|
||||
# - false (default)
|
||||
tmux_conf_new_window_retain_current_path=false
|
||||
|
||||
# new pane retains current path, possible values are:
|
||||
# - true (default)
|
||||
# - false
|
||||
tmux_conf_new_pane_retain_current_path=true
|
||||
|
||||
# new pane tries to reconnect ssh sessions (experimental), possible values are:
|
||||
# - true
|
||||
# - false (default)
|
||||
tmux_conf_new_pane_reconnect_ssh=true
|
||||
|
||||
# prompt for session name when creating a new session, possible values are:
|
||||
# - true
|
||||
# - false (default)
|
||||
tmux_conf_new_session_prompt=false
|
||||
|
||||
|
||||
# -- display -------------------------------------------------------------------
|
||||
|
||||
# RGB 24-bit colour support (tmux >= 2.2), possible values are:
|
||||
# - true
|
||||
# - false (default)
|
||||
tmux_conf_24b_colour=true
|
||||
|
||||
# default theme
|
||||
tmux_conf_theme_colour_1="#080808" # dark gray
|
||||
tmux_conf_theme_colour_2="#303030" # gray
|
||||
tmux_conf_theme_colour_3="#8a8a8a" # light gray
|
||||
tmux_conf_theme_colour_4="#00afff" # light blue
|
||||
tmux_conf_theme_colour_5="#ffff00" # yellow
|
||||
tmux_conf_theme_colour_6="#080808" # dark gray
|
||||
tmux_conf_theme_colour_7="#e4e4e4" # white
|
||||
tmux_conf_theme_colour_8="#080808" # dark gray
|
||||
tmux_conf_theme_colour_9="#ffff00" # yellow
|
||||
tmux_conf_theme_colour_10="#ff00af" # pink
|
||||
tmux_conf_theme_colour_11="#5fff00" # green
|
||||
tmux_conf_theme_colour_12="#8a8a8a" # light gray
|
||||
tmux_conf_theme_colour_13="#e4e4e4" # white
|
||||
tmux_conf_theme_colour_14="#080808" # dark gray
|
||||
tmux_conf_theme_colour_15="#080808" # dark gray
|
||||
tmux_conf_theme_colour_16="#d70000" # red
|
||||
tmux_conf_theme_colour_17="#e4e4e4" # white
|
||||
|
||||
# default theme (ansi)
|
||||
#tmux_conf_theme_colour_1="colour0"
|
||||
#tmux_conf_theme_colour_2="colour8"
|
||||
#tmux_conf_theme_colour_3="colour8"
|
||||
#tmux_conf_theme_colour_4="colour14"
|
||||
#tmux_conf_theme_colour_5="colour11"
|
||||
#tmux_conf_theme_colour_6="colour0"
|
||||
#tmux_conf_theme_colour_7="colour15"
|
||||
#tmux_conf_theme_colour_8="colour0"
|
||||
#tmux_conf_theme_colour_9="colour11"
|
||||
#tmux_conf_theme_colour_10="colour13"
|
||||
#tmux_conf_theme_colour_11="colour10"
|
||||
#tmux_conf_theme_colour_12="colour8"
|
||||
#tmux_conf_theme_colour_13="colour15"
|
||||
#tmux_conf_theme_colour_14="colour0"
|
||||
#tmux_conf_theme_colour_15="colour0"
|
||||
#tmux_conf_theme_colour_16="colour1"
|
||||
#tmux_conf_theme_colour_17="colour15"
|
||||
|
||||
# window style
|
||||
tmux_conf_theme_window_fg="default"
|
||||
tmux_conf_theme_window_bg="default"
|
||||
|
||||
# highlight focused pane (tmux >= 2.1), possible values are:
|
||||
# - true
|
||||
# - false (default)
|
||||
tmux_conf_theme_highlight_focused_pane=false
|
||||
|
||||
# focused pane colours:
|
||||
tmux_conf_theme_focused_pane_bg="$tmux_conf_theme_colour_2"
|
||||
|
||||
# pane border style, possible values are:
|
||||
# - thin (default)
|
||||
# - fat
|
||||
tmux_conf_theme_pane_border_style=thin
|
||||
|
||||
# pane borders colours:
|
||||
tmux_conf_theme_pane_border="$tmux_conf_theme_colour_2"
|
||||
tmux_conf_theme_pane_active_border="$tmux_conf_theme_colour_4"
|
||||
|
||||
# pane indicator colours (when you hit <prefix> + q)
|
||||
tmux_conf_theme_pane_indicator="$tmux_conf_theme_colour_4"
|
||||
tmux_conf_theme_pane_active_indicator="$tmux_conf_theme_colour_4"
|
||||
|
||||
# status line style
|
||||
tmux_conf_theme_message_fg="$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_message_bg="$tmux_conf_theme_colour_5"
|
||||
tmux_conf_theme_message_attr="bold"
|
||||
|
||||
# status line command style (<prefix> : Escape)
|
||||
tmux_conf_theme_message_command_fg="$tmux_conf_theme_colour_5"
|
||||
tmux_conf_theme_message_command_bg="$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_message_command_attr="bold"
|
||||
|
||||
# window modes style
|
||||
tmux_conf_theme_mode_fg="$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_mode_bg="$tmux_conf_theme_colour_5"
|
||||
tmux_conf_theme_mode_attr="bold"
|
||||
|
||||
# status line style
|
||||
tmux_conf_theme_status_fg="$tmux_conf_theme_colour_3"
|
||||
tmux_conf_theme_status_bg="$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_status_attr="none"
|
||||
|
||||
# terminal title
|
||||
# - built-in variables are:
|
||||
# - #{circled_window_index}
|
||||
# - #{circled_session_name}
|
||||
# - #{hostname}
|
||||
# - #{hostname_ssh}
|
||||
# - #{username}
|
||||
# - #{username_ssh}
|
||||
#tmux_conf_theme_terminal_title="#{username}@#{hostname}: #S - #I - #W"
|
||||
tmux_conf_theme_terminal_title=" "
|
||||
|
||||
# window status style
|
||||
# - built-in variables are:
|
||||
# - #{circled_window_index}
|
||||
# - #{circled_session_name}
|
||||
# - #{hostname}
|
||||
# - #{hostname_ssh}
|
||||
# - #{username}
|
||||
# - #{username_ssh}
|
||||
tmux_conf_theme_window_status_fg="$tmux_conf_theme_colour_3"
|
||||
tmux_conf_theme_window_status_bg="$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_window_status_attr="none"
|
||||
tmux_conf_theme_window_status_format="#I #W"
|
||||
#tmux_conf_theme_window_status_format="#{circled_window_index} #W"
|
||||
#tmux_conf_theme_window_status_format="#I #W#{?window_bell_flag,🔔,}#{?window_zoomed_flag,🔍,}"
|
||||
|
||||
# window current status style
|
||||
# - built-in variables are:
|
||||
# - #{circled_window_index}
|
||||
# - #{circled_session_name}
|
||||
# - #{hostname}
|
||||
# - #{hostname_ssh}
|
||||
# - #{username}
|
||||
# - #{username_ssh}
|
||||
tmux_conf_theme_window_status_current_fg="$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_window_status_current_bg="$tmux_conf_theme_colour_4"
|
||||
tmux_conf_theme_window_status_current_attr="bold"
|
||||
tmux_conf_theme_window_status_current_format="#I #W"
|
||||
#tmux_conf_theme_window_status_current_format="#{circled_window_index} #W"
|
||||
#tmux_conf_theme_window_status_current_format="#I #W#{?window_zoomed_flag,🔍,}"
|
||||
|
||||
# window activity status style
|
||||
tmux_conf_theme_window_status_activity_fg="default"
|
||||
tmux_conf_theme_window_status_activity_bg="default"
|
||||
tmux_conf_theme_window_status_activity_attr="underscore"
|
||||
|
||||
# window bell status style
|
||||
tmux_conf_theme_window_status_bell_fg="$tmux_conf_theme_colour_5"
|
||||
tmux_conf_theme_window_status_bell_bg="default"
|
||||
tmux_conf_theme_window_status_bell_attr="blink,bold"
|
||||
|
||||
# window last status style
|
||||
tmux_conf_theme_window_status_last_fg="$tmux_conf_theme_colour_4"
|
||||
tmux_conf_theme_window_status_last_bg="$tmux_conf_theme_colour_2"
|
||||
tmux_conf_theme_window_status_last_attr="none"
|
||||
|
||||
# status left/right sections separators
|
||||
#tmux_conf_theme_left_separator_main=""
|
||||
#tmux_conf_theme_left_separator_sub="|"
|
||||
#tmux_conf_theme_right_separator_main=""
|
||||
#tmux_conf_theme_right_separator_sub="|"
|
||||
tmux_conf_theme_left_separator_main="\uE0B0" # /!\ you don't need to install Powerline
|
||||
tmux_conf_theme_left_separator_sub="\uE0B1" # you only need fonts patched with
|
||||
tmux_conf_theme_right_separator_main="\uE0B2" # Powerline symbols or the standalone
|
||||
tmux_conf_theme_right_separator_sub="\uE0B3" # PowerlineSymbols.otf font, see README.md
|
||||
|
||||
# status left/right content:
|
||||
# - separate main sections with "|"
|
||||
# - separate subsections with ","
|
||||
# - built-in variables are:
|
||||
# - #{battery_bar}
|
||||
# - #{battery_hbar}
|
||||
# - #{battery_percentage}
|
||||
# - #{battery_status}
|
||||
# - #{battery_vbar}
|
||||
# - #{circled_session_name}
|
||||
# - #{hostname_ssh}
|
||||
# - #{hostname}
|
||||
# - #{loadavg}
|
||||
# - #{pairing}
|
||||
# - #{prefix}
|
||||
# - #{root}
|
||||
# - #{synchronized}
|
||||
# - #{uptime_y}
|
||||
# - #{uptime_d} (modulo 365 when #{uptime_y} is used)
|
||||
# - #{uptime_h}
|
||||
# - #{uptime_m}
|
||||
# - #{uptime_s}
|
||||
# - #{username}
|
||||
# - #{username_ssh}
|
||||
#tmux_conf_theme_status_left=" ❐ #S | ↑#{?uptime_y, #{uptime_y}y,}#{?uptime_d, #{uptime_d}d,}#{?uptime_h, #{uptime_h}h,}#{?uptime_m, #{uptime_m}m,} "
|
||||
tmux_conf_theme_status_left=" [#S] | #{username}@#{hostname} ,"
|
||||
#tmux_conf_theme_status_left=" [#S] "
|
||||
#tmux_conf_theme_status_right=" #{prefix}#{pairing}#{synchronized}#{?battery_status,#{battery_status},}#{?battery_bar, #{battery_bar},}#{?battery_percentage, #{battery_percentage},} , %R , %d %b | #{username}#{root} | #{hostname} "
|
||||
tmux_conf_theme_status_right=", %R , %d %b | #{battery_percentage} "
|
||||
|
||||
# status left style
|
||||
tmux_conf_theme_status_left_fg="$tmux_conf_theme_colour_1,$tmux_conf_theme_colour_12"
|
||||
tmux_conf_theme_status_left_bg="$tmux_conf_theme_colour_3,$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_status_left_attr="bold,none,none"
|
||||
|
||||
# status right style
|
||||
tmux_conf_theme_status_right_fg="$tmux_conf_theme_colour_12,$tmux_conf_theme_colour_1"
|
||||
tmux_conf_theme_status_right_bg="$tmux_conf_theme_colour_1,$tmux_conf_theme_colour_3"
|
||||
tmux_conf_theme_status_right_attr="none,none,none"
|
||||
|
||||
# pairing indicator
|
||||
tmux_conf_theme_pairing="⚇" # U+2687
|
||||
tmux_conf_theme_pairing_fg="none"
|
||||
tmux_conf_theme_pairing_bg="none"
|
||||
tmux_conf_theme_pairing_attr="none"
|
||||
|
||||
# prefix indicator
|
||||
tmux_conf_theme_prefix="⌨" # U+2328
|
||||
tmux_conf_theme_prefix_fg="none"
|
||||
tmux_conf_theme_prefix_bg="none"
|
||||
tmux_conf_theme_prefix_attr="none"
|
||||
|
||||
# root indicator
|
||||
tmux_conf_theme_root="!"
|
||||
tmux_conf_theme_root_fg="none"
|
||||
tmux_conf_theme_root_bg="none"
|
||||
tmux_conf_theme_root_attr="bold,blink"
|
||||
|
||||
# synchronized indicator
|
||||
tmux_conf_theme_synchronized="⚏" # U+268F
|
||||
tmux_conf_theme_synchronized_fg="none"
|
||||
tmux_conf_theme_synchronized_bg="none"
|
||||
tmux_conf_theme_synchronized_attr="none"
|
||||
|
||||
# battery bar symbols
|
||||
tmux_conf_battery_bar_symbol_full="◼"
|
||||
tmux_conf_battery_bar_symbol_empty="◻"
|
||||
#tmux_conf_battery_bar_symbol_full="♥"
|
||||
#tmux_conf_battery_bar_symbol_empty="·"
|
||||
|
||||
# battery bar length (in number of symbols), possible values are:
|
||||
# - auto
|
||||
# - a number, e.g. 5
|
||||
tmux_conf_battery_bar_length="auto"
|
||||
|
||||
# battery bar palette, possible values are:
|
||||
# - gradient (default)
|
||||
# - heat
|
||||
# - "colour_full_fg,colour_empty_fg,colour_bg"
|
||||
tmux_conf_battery_bar_palette="gradient"
|
||||
#tmux_conf_battery_bar_palette="#d70000,#e4e4e4,#000000" # red, white, black
|
||||
|
||||
# battery hbar palette, possible values are:
|
||||
# - gradient (default)
|
||||
# - heat
|
||||
# - "colour_low,colour_half,colour_full"
|
||||
tmux_conf_battery_hbar_palette="gradient"
|
||||
#tmux_conf_battery_hbar_palette="#d70000,#ff5f00,#5fff00" # red, orange, green
|
||||
|
||||
# battery vbar palette, possible values are:
|
||||
# - gradient (default)
|
||||
# - heat
|
||||
# - "colour_low,colour_half,colour_full"
|
||||
tmux_conf_battery_vbar_palette="gradient"
|
||||
#tmux_conf_battery_vbar_palette="#d70000,#ff5f00,#5fff00" # red, orange, green
|
||||
|
||||
# symbols used to indicate whether battery is charging or discharging
|
||||
tmux_conf_battery_status_charging="↑" # U+2191
|
||||
tmux_conf_battery_status_discharging="↓" # U+2193
|
||||
#tmux_conf_battery_status_charging="🔌" # U+1F50C
|
||||
#tmux_conf_battery_status_discharging="🔋" # U+1F50B
|
||||
|
||||
# clock style (when you hit <prefix> + t)
|
||||
# you may want to use %I:%M %p in place of %R in tmux_conf_theme_status_right
|
||||
tmux_conf_theme_clock_colour="$tmux_conf_theme_colour_4"
|
||||
tmux_conf_theme_clock_style="24"
|
||||
|
||||
|
||||
# -- clipboard -----------------------------------------------------------------
|
||||
|
||||
# in copy mode, copying selection also copies to the OS clipboard
|
||||
# - true
|
||||
# - false (default)
|
||||
# on macOS, this requires installing reattach-to-user-namespace, see README.md
|
||||
# on Linux, this requires xsel or xclip
|
||||
tmux_conf_copy_to_os_clipboard=true
|
||||
|
||||
|
||||
# -- user customizations -------------------------------------------------------
|
||||
# this is the place to override or undo settings
|
||||
|
||||
# increase history size
|
||||
set -g history-limit 2048
|
||||
|
||||
# start with mouse mode enabled
|
||||
set -g mouse on
|
||||
|
||||
# force Vi mode
|
||||
# really you should export VISUAL or EDITOR environment variable, see manual
|
||||
#set -g status-keys vi
|
||||
#set -g mode-keys vi
|
||||
|
||||
# replace C-b by C-a instead of using both prefixes
|
||||
#set -gu prefix2
|
||||
#unbind C-a
|
||||
#unbind C-b
|
||||
#set -g prefix C-a
|
||||
#bind C-a send-prefix
|
||||
|
||||
# move status line to top
|
||||
#set -g status-position top
|
||||
|
||||
####### FULL CUSTOM ########
|
||||
|
||||
#bind '+' split-window -h
|
||||
#bind '#' split-window -v
|
||||
|
||||
bind -r '+' split-window -p 50 -h -c "#{pane_current_path}"# \; set -u pane-active-border-style
|
||||
bind -r '#' split-window -p 50 -v -c "#{pane_current_path}"# \; set -u pane-active-border-style
|
||||
|
||||
bind -n C-Left select-pane -L
|
||||
bind -n C-Right select-pane -R
|
||||
bind -n C-Up select-pane -U
|
||||
bind -n C-Down select-pane -D
|
||||
|
||||
bind -r Tab next-window
|
||||
#bind c new-window -c '#{pane_current_path}'
|
||||
bind Z resize-pane -Z
|
||||
|
||||
set -g mouse on
|
||||
|
||||
setw -g monitor-activity on
|
||||
set -g visual-activity on
|
||||
|
||||
set -g history-limit 2048
|
||||
set -s escape-time 50
|
||||
#set -g default-terminal "screen-256color"
|
||||
|
||||
set -g status-bg black
|
||||
set -g status-fg white
|
||||
|
||||
set -g window-status-current-style bg=white,fg=black,bold
|
||||
|
||||
#set -g status-justify centre
|
||||
set -g status-interval 60
|
||||
set -g status-left-length 30
|
||||
set -g status-left '#[fg=green][#S] #(whoami)@#(hostname) \uE0B0 #[bg=black] '
|
||||
set -g status-right '#[fg=yellow]#(cut -d " " -f 1-3 /proc/loadavg)#[default] #[fg=white]%H:%M#[default]'
|
||||
|
||||
#set-option -ga terminal-overrides ",xterm-256color:Tc"
|
||||
|
||||
###bind y run-shell "tmux show-buffer | xclip -sel clip -i" \; display-message "Copied tmux buffer to system clipboard"
|
||||
#bind -T copy-mode y send-keys -X copy-pipe-and-cancel "xsel -i -p && xsel -o -p | xsel -i -b"
|
||||
#bind C-y run "xsel -o | tmux load-buffer - ; tmux paste-buffer"
|
||||
|
||||
# -- custom variables ----------------------------------------------------------
|
||||
# to define a custom #{foo} variable, define a POSIX shell function between the
|
||||
# '# EOF' and the '# "$@"' lines. Please note that the opening brace { character
|
||||
# must be on the same line as the function name otherwise the parse won't detect
|
||||
# it.
|
||||
#
|
||||
# then, use #{foo} in e.g. the 'tmux_conf_theme_status_left' or the
|
||||
# 'tmux_conf_theme_status_right' variables.
|
||||
|
||||
# # /!\ do not remove the following line
|
||||
# EOF
|
||||
#
|
||||
# weather() {
|
||||
# curl -m 1 wttr.in?format=3 2>/dev/null
|
||||
# sleep 900 # sleep for 15 minutes, throttle network requests whatever the value of status-interval
|
||||
# }
|
||||
#
|
||||
# online() {
|
||||
# ping -t 1 -c 1 1.1.1.1 >/dev/null 2>&1 && printf '✔' || printf '✘'
|
||||
# }
|
||||
#
|
||||
# "$@"
|
||||
# # /!\ do not remove the previous line
|
131
dotfiles/.zshrc
Normal file
131
dotfiles/.zshrc
Normal file
@ -0,0 +1,131 @@
|
||||
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
|
||||
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
|
||||
fi
|
||||
export ZSH="$HOME/.oh-my-zsh"
|
||||
ZSH_THEME="powerlevel10k/powerlevel10k"
|
||||
HIST_STAMPS="dd.mm.yyyy"
|
||||
plugins=(git)
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
autoload -U +X bashcompinit && bashcompinit
|
||||
[ -f /usr/share/bash-completion/completions/dnf ] && source /usr/share/bash-completion/completions/dnf
|
||||
|
||||
######################
|
||||
# User configuration #
|
||||
######################
|
||||
|
||||
export EDITOR='nvim'
|
||||
|
||||
if [ $TILIX_ID ] || [ $VTE_VERSION ]; then
|
||||
[ -f /etc/profile.d/vte.sh ] && source /etc/profile.d/vte.sh
|
||||
fi
|
||||
|
||||
#export LS_COLORS='rs=0:no=00:mi=00:mh=00:ln=01;36:or=01;31:di=01;34:ow=04;01;34:st=34:tw=04;34:pi=01;33:so=01;33:do=01;33:bd=01;33:cd=01;33:su=01;35:sg=01;35:ca=01;35:ex=01;32:'
|
||||
|
||||
##########
|
||||
|
||||
# lang
|
||||
alias ptpython="python -m ptpython"
|
||||
alias ptpy="python -m ptpython"
|
||||
alias py13='python3.13'
|
||||
alias py12='python3.12'
|
||||
alias py10='python3.10'
|
||||
alias bpytop="python -m bpytop"
|
||||
|
||||
# python venv
|
||||
alias pvcreate="python -m venv .venv"
|
||||
alias pvactivate="source .venv/bin/activate"
|
||||
alias pvinstall="echo 'Creating Python-venv' && pvcreate && echo 'Entering venv' && pvactivate && echo 'Upgrading pip' && pip install pip --upgrade && echo 'Installing Dependencies' && pip install -r requirements.txt && echo 'Done.'"
|
||||
|
||||
# qol
|
||||
alias cls="clear"
|
||||
alias root="sudo su --shell /bin/zsh"
|
||||
alias open="xdg-open"
|
||||
alias filenum="du -a | cut -d/ -f2 | sort | uniq -c | sort -nr"
|
||||
alias pg="progress"
|
||||
alias hist="history"
|
||||
alias untar="tar -zxvf"
|
||||
alias neofetch=fastfetch
|
||||
|
||||
# grep
|
||||
alias antigrep="grep -v"
|
||||
alias grep2="grep -A 2 -B 2"
|
||||
alias grep4="grep -A 4 -B 4"
|
||||
alias grep8="grep -A 8 -B 8"
|
||||
alias grep16="grep -A 16 -B 16"
|
||||
alias grep32="grep -A 32 -B 32"
|
||||
alias ag="alias | grep"
|
||||
|
||||
# packages
|
||||
alias get="sudo dnf install"
|
||||
alias upd="sudo dnf check-upgrade"
|
||||
alias upg="sudo dnf upgrade"
|
||||
|
||||
# chars
|
||||
alias c="clear"
|
||||
alias t="bpytop"
|
||||
alias p="ptpy"
|
||||
alias h="history | grep"
|
||||
alias v="nvim"
|
||||
alias n="nano"
|
||||
alias o="open"
|
||||
alias e="\d"
|
||||
alias ":q"="exit"
|
||||
|
||||
# git
|
||||
alias gs="git status"
|
||||
alias gt="git log --all --graph --decorate --oneline --abbrev-commit"
|
||||
alias gnoc='git shortlog -sn | cat' # Number Of Commit by user
|
||||
alias gloc='git ls-files | while read f; do git blame -w -M -C -C --line-porcelain "$f" | grep -I "^author "; done | sort -f | uniq -ic | sort -n --reverse' # Lines Of Code by user (in final version)
|
||||
alias gpa='gaa && gc -m "." && gp -4'
|
||||
|
||||
# dirs
|
||||
alias tmp="cd ~/.tmp"
|
||||
|
||||
# extensions
|
||||
alias sudo="sudo "
|
||||
alias watch="watch "
|
||||
alias watch1="watch -n 1 "
|
||||
|
||||
# better ls via lsd
|
||||
alias ls="lsd"
|
||||
alias l="ls -1"
|
||||
alias la="ls -A"
|
||||
alias laa="ls -a"
|
||||
alias lsa="ls -lA"
|
||||
alias lla="ls -lA"
|
||||
alias ltree="ls --tree"
|
||||
alias d0="ls --tree"
|
||||
alias d="ls --depth 1 --tree"
|
||||
alias d1="ls --depth 1 --tree"
|
||||
alias d2="ls --depth 2 --tree"
|
||||
alias d3="ls --depth 3 --tree"
|
||||
alias d4="ls --depth 4 --tree"
|
||||
alias d5="ls --depth 5 --tree"
|
||||
alias d6="ls --depth 6 --tree"
|
||||
|
||||
# more ls
|
||||
alias lo="\ls --color=tty"
|
||||
alias dtree="tree --du -h"
|
||||
alias gtree="tree --du -h -F -C | grep 'G] ' --color=never"
|
||||
|
||||
# better cat via batcat
|
||||
alias bat="bat --pager ''"
|
||||
alias pat="bat --pager '' --plain"
|
||||
alias lat="bat"
|
||||
|
||||
# more fancy batcat stuff
|
||||
alias man="batman"
|
||||
|
||||
# tmux
|
||||
alias s="tmux"
|
||||
alias sa="tmux attach"
|
||||
alias sn="tmux new -s"
|
||||
alias san="tmux attach -t"
|
||||
alias sl="tmux ls"
|
||||
alias sk="tmux kill-session -t"
|
||||
alias ska="tmux kill-session -a"
|
||||
|
||||
#####
|
||||
|
||||
export PATH=$PATH:$HOME/.local/bin
|
||||
|
13
install.conf
Normal file
13
install.conf
Normal file
@ -0,0 +1,13 @@
|
||||
DRIVE1 /dev/sda
|
||||
DRIVE2 /dev/sdb
|
||||
HOSTNAME nullpoint
|
||||
BOOTLOADER grub
|
||||
SWRAID 1
|
||||
SWRAIDLEVEL 1
|
||||
FILESYSTEM xfs
|
||||
IMAGE AlmaLinux-9.3-Generic
|
||||
CRYPTPASSWORD changeme
|
||||
|
||||
PART /boot/efi vfat 512M
|
||||
PART /boot xfs 2G
|
||||
PART / xfs all
|
447
install.sh
Executable file → Normal file
447
install.sh
Executable file → Normal file
@ -1,4 +1,9 @@
|
||||
#!/bin/bash
|
||||
# nullpoint installer - run this from Hetzner rescue mode
|
||||
# wget -qO- https://git.dominik-roth.eu/dodox/nullpoint/raw/branch/master/install.sh | bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BANNER=$(cat << "EOF"
|
||||
:^7J5GB##&&##GPY?~:
|
||||
^75B&@@@@@@&&&@@@@@@@#GJ~:
|
||||
@ -25,389 +30,113 @@ J@@@5 :#@@@Y: :Y@@@B: 5@@@J
|
||||
EOF
|
||||
)
|
||||
|
||||
TANG_SERVERS=(
|
||||
# "https://tang1.example.com your-thumbprint-1"
|
||||
# "https://tang2.example.com your-thumbprint-2"
|
||||
)
|
||||
TPM_PCR_BANK="sha256"
|
||||
TPM_PCR_IDS="0,1,2,3,4,5,6,7,8"
|
||||
FEDORA_VERSION="42"
|
||||
FEDORA_USER="null"
|
||||
ENABLE_MOTD=true
|
||||
SSH_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOkoTn2NreAXMriOUqzyj3YoFW6jMo9B5B+3R5k8yrMi dodox@dodox-ProArt"
|
||||
|
||||
########################################################
|
||||
# Config End
|
||||
########################################################
|
||||
|
||||
set -euo pipefail
|
||||
alias c="clear"
|
||||
alias cls="clear"
|
||||
clear
|
||||
echo -e "\n$BANNER"
|
||||
echo -e "\n[+] Starting installation..."
|
||||
echo -e "\n[+] nullpoint installer starting..."
|
||||
|
||||
# Check for TPM
|
||||
echo "[+] Checking for TPM..."
|
||||
if [ ! -d "/sys/class/tpm/tpm0" ]; then
|
||||
echo "WARNING: No TPM detected!"
|
||||
echo "This system will not be able to use TPM-based boot verification."
|
||||
echo "You might need to enable TPM in the BIOS. (On Hetzner make a support ticket for KVM access)"
|
||||
read -p "Continue without TPM? [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Installation aborted."
|
||||
exit 1
|
||||
fi
|
||||
echo "Proceeding without TPM..."
|
||||
TPM_ENABLED=false
|
||||
else
|
||||
echo "TPM detected."
|
||||
TPM_ENABLED=true
|
||||
# Check if we're in Hetzner rescue mode
|
||||
if [ ! -f /etc/hetzner-build ]; then
|
||||
echo "ERROR: This script must be run from Hetzner rescue mode!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for SSH key
|
||||
if [ -z "${SSH_KEY:-}" ]; then
|
||||
echo "No SSH key provided. Please enter your public SSH key:"
|
||||
# Get SSH key from current session
|
||||
echo "[+] Detecting SSH key from current session..."
|
||||
SSH_KEY=$(grep "^ssh-" ~/.ssh/authorized_keys | head -1)
|
||||
if [ -z "$SSH_KEY" ]; then
|
||||
echo "ERROR: No SSH key found in authorized_keys!"
|
||||
echo "Please enter your SSH public key:"
|
||||
read -r SSH_KEY
|
||||
if [ -z "$SSH_KEY" ]; then
|
||||
echo "Error: SSH key is required for installation"
|
||||
echo "SSH key is required!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Found SSH key: ${SSH_KEY:0:50}..."
|
||||
|
||||
# Ask for hostname
|
||||
echo -e "\n[+] Server configuration"
|
||||
read -p "Enter hostname [nullpoint]: " HOSTNAME
|
||||
HOSTNAME=${HOSTNAME:-nullpoint}
|
||||
|
||||
# Ask for username
|
||||
read -p "Enter username for admin account [null]: " USERNAME
|
||||
USERNAME=${USERNAME:-null}
|
||||
|
||||
# Generate secure LUKS passphrase
|
||||
echo "[+] Generating secure LUKS passphrase..."
|
||||
LUKS_PASSPHRASE=$(openssl rand -base64 30)
|
||||
echo -e "\n[+] Generating secure LUKS passphrase..."
|
||||
LUKS_PASS=$(openssl rand -base64 30)
|
||||
|
||||
echo "----------------------------------------"
|
||||
echo "Generated LUKS passphrase:"
|
||||
echo "${LUKS_PASSPHRASE}"
|
||||
echo "----------------------------------------"
|
||||
echo "Please save these credentials securely. You will need them for recovery."
|
||||
echo "Press Enter to continue..."
|
||||
echo -e "\n================================================"
|
||||
echo "LUKS PASSPHRASE (SAVE THIS!):"
|
||||
echo "$LUKS_PASS"
|
||||
echo "================================================"
|
||||
echo -e "\nPress Enter when you've saved the passphrase..."
|
||||
read
|
||||
|
||||
# Install required packages
|
||||
apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y genisoimage grub-efi-amd64-bin util-linux kexec-tools
|
||||
|
||||
# Detect disk naming scheme and set variables
|
||||
echo "[+] Detecting disk configuration..."
|
||||
DISKS=($(lsblk -d -n -o NAME | grep -E '^(sd[a-z]|nvme[0-9]+n[0-9]+)$' | sort))
|
||||
if [ ${#DISKS[@]} -lt 1 ]; then
|
||||
echo "Error: Expected at least 1 disk, found ${#DISKS[@]}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DISK="/dev/${DISKS[0]}"
|
||||
|
||||
# Create a small partition for installer files
|
||||
echo "[+] Creating installer partition..."
|
||||
parted -s $DISK mklabel gpt
|
||||
parted -s $DISK mkpart primary ext4 0% 2GB
|
||||
parted -s $DISK name 1 installer
|
||||
mkfs.ext4 -L installer ${DISK}1
|
||||
mkdir -p /mnt/installer
|
||||
mount ${DISK}1 /mnt/installer
|
||||
|
||||
# Download Fedora installer
|
||||
echo "[+] Downloading Fedora installer..."
|
||||
wget -O /mnt/installer/Fedora-Server-netinst-x86_64-${FEDORA_VERSION}-1.1.iso "https://download.fedoraproject.org/pub/fedora/linux/releases/${FEDORA_VERSION}/Server/x86_64/iso/Fedora-Server-netinst-x86_64-${FEDORA_VERSION}-1.1.iso"
|
||||
|
||||
# Mount Fedora ISO
|
||||
echo "[+] Mounting Fedora installer..."
|
||||
mkdir -p /mnt/iso
|
||||
mount -o loop /mnt/installer/Fedora-Server-netinst-x86_64-${FEDORA_VERSION}-1.1.iso /mnt/iso
|
||||
|
||||
# Get current IP address and gateway from first non-loopback interface
|
||||
echo "[+] Detecting current IP address and gateway..."
|
||||
INTERFACE=$(ip -o -4 route show to default | awk '{print $5}' | head -n1)
|
||||
IPV4=$(ip -4 addr show $INTERFACE | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
|
||||
GATEWAY=$(ip route show default | awk '/default/ {print $3}')
|
||||
|
||||
echo "[+] Detected network configuration:"
|
||||
echo "Interface: $INTERFACE"
|
||||
echo "IP: $IPV4"
|
||||
echo "Gateway: $GATEWAY"
|
||||
|
||||
# Create kickstart file
|
||||
echo "[+] Creating kickstart configuration..."
|
||||
cat > /mnt/installer/ks.cfg << 'KICKSTART'
|
||||
# Fedora Server installation with our secure setup
|
||||
text
|
||||
lang en_US.UTF-8
|
||||
keyboard us
|
||||
timezone --utc Etc/UTC
|
||||
|
||||
# Security settings
|
||||
selinux --enforcing
|
||||
rootpw --lock
|
||||
user --name=${FEDORA_USER} --groups=wheel --shell=/bin/bash --lock
|
||||
|
||||
# SSH setup
|
||||
sshkey --username=${FEDORA_USER} "${SSH_KEY}"
|
||||
|
||||
# Network - let installer detect interface
|
||||
network --bootproto=static --ip=${IPV4} --netmask=255.255.255.255 --gateway=${GATEWAY} --nameserver=185.12.64.1 --nameserver=185.12.64.2 --activate
|
||||
|
||||
# Bootloader
|
||||
bootloader --timeout=1 --location=mbr --append="no_timer_check console=tty1 console=ttyS0,115200n8"
|
||||
|
||||
# Services
|
||||
services --enabled=sshd,clevis-luks-askpass,dropbear
|
||||
|
||||
# Use existing partitions
|
||||
part /boot/efi --fstype=vfat --onpart=${PART1}
|
||||
part /boot --fstype=ext4 --onpart=/dev/md0
|
||||
part / --fstype=btrfs --onpart=/dev/mapper/root_a
|
||||
|
||||
# Packages
|
||||
%packages
|
||||
@^server-product-environment
|
||||
clevis
|
||||
clevis-luks
|
||||
clevis-tang
|
||||
clevis-tpm2
|
||||
tpm2-tools
|
||||
tpm2-tss
|
||||
cryptsetup
|
||||
btrfs-progs
|
||||
mdadm
|
||||
dropbear
|
||||
git
|
||||
zsh
|
||||
lsd
|
||||
bat
|
||||
tmux
|
||||
neovim
|
||||
fortune-mod
|
||||
cowsay
|
||||
lolcat
|
||||
xclip
|
||||
python3-pip
|
||||
%end
|
||||
|
||||
# Pre-installation
|
||||
%pre
|
||||
#!/bin/bash
|
||||
|
||||
# Use the LUKS passphrase from rescue script
|
||||
LUKS_PASSPHRASE="${LUKS_PASSPHRASE}"
|
||||
echo "\$LUKS_PASSPHRASE" > /tmp/luks.key
|
||||
chmod 600 /tmp/luks.key
|
||||
|
||||
# Detect disk naming scheme and set variables
|
||||
DISKS=($(lsblk -d -n -o NAME | grep -E '^(sd[a-z]|nvme[0-9]+n[0-9]+)$' | sort))
|
||||
if [ ${#DISKS[@]} -ne 2 ]; then
|
||||
echo "Error: Expected exactly 2 disks, found ${#DISKS[@]}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set disk variables
|
||||
DISK1="/dev/${DISKS[0]}"
|
||||
DISK2="/dev/${DISKS[1]}"
|
||||
|
||||
# Stop any existing RAID arrays
|
||||
mdadm --stop /dev/md0 2>/dev/null || true
|
||||
|
||||
# Unmount any existing partitions
|
||||
for disk in $DISK1 $DISK2; do
|
||||
umount -f $disk* 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Stop any device mapper devices
|
||||
dmsetup remove_all 2>/dev/null || true
|
||||
|
||||
# Disconnect NVMe devices if present
|
||||
if [[ "$DISK1" =~ nvme ]] || [[ "$DISK2" =~ nvme ]]; then
|
||||
nvme disconnect-all
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# Zero out partition tables
|
||||
for disk in $DISK1 $DISK2; do
|
||||
if [[ "$disk" =~ nvme ]]; then
|
||||
blkdiscard -f $disk
|
||||
else
|
||||
dd if=/dev/zero of=$disk bs=1M count=2 conv=fsync
|
||||
dd if=/dev/zero of=$disk bs=1M seek=$(($(blockdev --getsz $disk) / 2048 - 2)) count=2 conv=fsync
|
||||
fi
|
||||
sync
|
||||
done
|
||||
|
||||
# Create partitions
|
||||
for disk in $DISK1 $DISK2; do
|
||||
parted -s $disk mklabel gpt
|
||||
parted -s $disk mkpart primary fat32 0% 512MB
|
||||
parted -s $disk mkpart primary ext4 512MB 1.5GB
|
||||
parted -s $disk mkpart primary ext4 1.5GB 100%
|
||||
parted -s $disk set 1 boot on
|
||||
sync
|
||||
done
|
||||
|
||||
# For NVMe disks, we need to append 'p' to partition numbers
|
||||
if [[ "$DISK1" =~ nvme ]]; then
|
||||
PART1="${DISK1}p1"
|
||||
PART2="${DISK1}p2"
|
||||
PART3="${DISK1}p3"
|
||||
PART4="${DISK2}p1"
|
||||
PART5="${DISK2}p2"
|
||||
PART6="${DISK2}p3"
|
||||
# Clone or download the nullpoint repo
|
||||
echo "[+] Downloading nullpoint configuration..."
|
||||
if command -v git &> /dev/null; then
|
||||
git clone https://git.dominik-roth.eu/dodox/nullpoint.git /tmp/nullpoint
|
||||
else
|
||||
PART1="${DISK1}1"
|
||||
PART2="${DISK1}2"
|
||||
PART3="${DISK1}3"
|
||||
PART4="${DISK2}1"
|
||||
PART5="${DISK2}2"
|
||||
PART6="${DISK2}3"
|
||||
echo "ERROR: git not available and wget fallback insufficient for dotfiles"
|
||||
echo "Please install git or use manual installation method"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create EFI partitions
|
||||
mkfs.vfat -F 32 $PART1
|
||||
mkfs.vfat -F 32 $PART4
|
||||
# Update install.conf
|
||||
echo "[+] Configuring installation..."
|
||||
cd /tmp/nullpoint
|
||||
sed -i "s/^HOSTNAME .*/HOSTNAME $HOSTNAME/" install.conf
|
||||
sed -i "s/^CRYPTPASSWORD .*/CRYPTPASSWORD $LUKS_PASS/" install.conf
|
||||
|
||||
# Create boot RAID1
|
||||
mdadm --create /dev/md0 --level=1 --raid-devices=2 --metadata=0.90 --force --run $PART2 $PART5
|
||||
mkfs.ext4 /dev/md0
|
||||
# Update post-install.sh
|
||||
sed -i "s/^ALMA_USER=.*/ALMA_USER=\"$USERNAME\"/" post-install.sh
|
||||
sed -i "s|^SSH_KEY=.*|SSH_KEY=\"$SSH_KEY\"|" post-install.sh
|
||||
|
||||
# Create LUKS volumes
|
||||
echo "$LUKS_PASSPHRASE" | cryptsetup luksFormat $PART3 --type luks2
|
||||
echo "$LUKS_PASSPHRASE" | cryptsetup luksFormat $PART6 --type luks2
|
||||
# Copy to root directory where installimage expects them
|
||||
cp install.conf /root/
|
||||
cp post-install.sh /root/
|
||||
chmod +x /root/post-install.sh
|
||||
|
||||
# Open LUKS volumes
|
||||
echo "$LUKS_PASSPHRASE" | cryptsetup luksOpen $PART3 root_a
|
||||
echo "$LUKS_PASSPHRASE" | cryptsetup luksOpen $PART6 root_b
|
||||
|
||||
# Create BTRFS RAID1
|
||||
mkfs.btrfs -f -d raid1 -m raid1 /dev/mapper/root_a /dev/mapper/root_b
|
||||
|
||||
# Create subvolumes
|
||||
mount /dev/mapper/root_a /mnt/sysimage
|
||||
btrfs subvolume create /mnt/sysimage/@root
|
||||
btrfs subvolume create /mnt/sysimage/@home
|
||||
btrfs subvolume create /mnt/sysimage/@db
|
||||
chattr +C /mnt/sysimage/@db
|
||||
|
||||
# Configure Clevis
|
||||
if [ ${#TANG_SERVERS[@]} -gt 0 ] || [ "$TPM_ENABLED" = true ]; then
|
||||
mkdir -p /mnt/sysimage/etc/clevis
|
||||
|
||||
# Build Tang servers JSON array if we have any
|
||||
if [ ${#TANG_SERVERS[@]} -gt 0 ]; then
|
||||
TANG_JSON="["
|
||||
for server in "${TANG_SERVERS[@]}"; do
|
||||
read -r url thumbprint <<< "$server"
|
||||
TANG_JSON+="{\"url\":\"$url\",\"thumbprint\":\"$thumbprint\"},"
|
||||
done
|
||||
TANG_JSON="${TANG_JSON%,}]" # Remove trailing comma and close array
|
||||
fi
|
||||
|
||||
# Calculate t value based on enabled methods
|
||||
T_VALUE=1
|
||||
if [ ${#TANG_SERVERS[@]} -gt 0 ] && [ "$TPM_ENABLED" = true ]; then
|
||||
T_VALUE=2
|
||||
fi
|
||||
|
||||
# Create Clevis config
|
||||
cat > /mnt/sysimage/etc/clevis/clevis.conf << EOF
|
||||
{
|
||||
"t": $T_VALUE,
|
||||
"pins": {
|
||||
$([ "$TPM_ENABLED" = true ] && echo "\"tpm2\": {
|
||||
\"pcr_bank\": \"$TPM_PCR_BANK\",
|
||||
\"pcr_ids\": \"$TPM_PCR_IDS\"
|
||||
},")
|
||||
$([ ${#TANG_SERVERS[@]} -gt 0 ] && echo "\"tang\": {
|
||||
\"t\": 1,
|
||||
\"tang\": $TANG_JSON
|
||||
}")
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Bind LUKS volumes
|
||||
clevis luks bind -d $PART3 sss -c /mnt/sysimage/etc/clevis/clevis.conf
|
||||
clevis luks bind -d $PART6 sss -c /mnt/sysimage/etc/clevis/clevis.conf
|
||||
# Ask for optional features
|
||||
echo -e "\n[+] Optional features:"
|
||||
read -p "Do you have a TPM and want to use it? [y/N]: " USE_TPM
|
||||
if [[ "$USE_TPM" =~ ^[Yy]$ ]]; then
|
||||
echo "TPM will be configured if available."
|
||||
else
|
||||
sed -i 's/^TPM_ENABLED=.*/TPM_ENABLED=false/' /root/post-install.sh
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
umount /mnt/sysimage
|
||||
%end
|
||||
|
||||
# Post-installation
|
||||
%post
|
||||
# Configure network with static IP (Hetzner dedicated server style)
|
||||
cat > /etc/sysconfig/network-scripts/ifcfg-ens3 << EOF
|
||||
DEVICE=ens3
|
||||
ONBOOT=yes
|
||||
BOOTPROTO=static
|
||||
IPADDR=$IPV4
|
||||
NETMASK=255.255.255.255
|
||||
SCOPE="peer $GATEWAY"
|
||||
EOF
|
||||
|
||||
# Create route file
|
||||
cat > /etc/sysconfig/network-scripts/route-ens3 << EOF
|
||||
ADDRESS0=0.0.0.0
|
||||
NETMASK0=0.0.0.0
|
||||
GATEWAY0=$GATEWAY
|
||||
EOF
|
||||
|
||||
# Reload network configuration
|
||||
nmcli con reload || true
|
||||
nmcli con up ens3 || true
|
||||
|
||||
# Update fstab
|
||||
cat > /etc/fstab << "FSTAB"
|
||||
${PART1} /boot/efi vfat defaults 1 2
|
||||
/dev/md0 /boot ext4 defaults 1 2
|
||||
/dev/mapper/root_a / btrfs subvol=@root,defaults,noatime 0 0
|
||||
/dev/mapper/root_a /home btrfs subvol=@home,defaults,noatime 0 0
|
||||
/dev/mapper/root_a /db btrfs subvol=@db,defaults,noatime,nodatacow 0 0
|
||||
FSTAB
|
||||
|
||||
# Configure dropbear for early SSH access
|
||||
mkdir -p /etc/dracut.conf.d
|
||||
cat > /etc/dracut.conf.d/dropbear.conf << "DROPBEAR"
|
||||
add_drivers+=" dropbear "
|
||||
install_optional_items=yes
|
||||
DROPBEAR
|
||||
|
||||
# Add SSH key to dropbear
|
||||
mkdir -p /etc/dropbear
|
||||
echo "$SSH_KEY" > /etc/dropbear/authorized_keys
|
||||
chmod 600 /etc/dropbear/authorized_keys
|
||||
|
||||
# Regenerate initramfs with dropbear
|
||||
dracut -f
|
||||
|
||||
# Set up MOTD
|
||||
if [ "$ENABLE_MOTD" = true ]; then
|
||||
cat > /etc/motd << "MOTD"
|
||||
$BANNER
|
||||
MOTD
|
||||
read -p "Do you have Tang servers configured? [y/N]: " USE_TANG
|
||||
if [[ "$USE_TANG" =~ ^[Yy]$ ]]; then
|
||||
echo "Please edit /root/post-install.sh after installation to add Tang servers."
|
||||
fi
|
||||
|
||||
# Enable required services
|
||||
systemctl enable clevis-luks-askpass
|
||||
systemctl enable dropbear
|
||||
# Final confirmation
|
||||
echo -e "\n[+] Ready to install with these settings:"
|
||||
echo " Hostname: $HOSTNAME"
|
||||
echo " Username: $USERNAME"
|
||||
echo " SSH Key: ${SSH_KEY:0:50}..."
|
||||
echo " LUKS Passphrase: [HIDDEN]"
|
||||
echo ""
|
||||
read -p "Proceed with installation? [Y/n]: " CONFIRM
|
||||
if [[ "$CONFIRM" =~ ^[Nn]$ ]]; then
|
||||
echo "Installation cancelled."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Force SELinux relabel on next boot
|
||||
touch /.autorelabel
|
||||
%end
|
||||
KICKSTART
|
||||
# Run the installer
|
||||
echo -e "\n[+] Starting Hetzner installimage..."
|
||||
echo "The installer will now run. Follow any prompts if needed."
|
||||
echo ""
|
||||
installimage -a -c /root/install.conf -s /root/post-install.sh
|
||||
|
||||
# Get actual ISO label
|
||||
ISO_LABEL=$(isoinfo -d -i /mnt/installer/Fedora-Server-netinst-x86_64-${FEDORA_VERSION}-1.1.iso | grep "Volume id:" | cut -d: -f2 | tr -d ' ')
|
||||
|
||||
# Set IP-related kernel boot params for installer
|
||||
KERNEL_NET_PARAMS="ip=$IPV4::$GATEWAY:255.255.255.255::ens3:none nameserver=185.12.64.1 nameserver=185.12.64.2"
|
||||
|
||||
echo "[+] Configuration complete. Starting installation with kexec..."
|
||||
echo "----------------------------------------"
|
||||
cat /mnt/installer/ks.cfg
|
||||
echo "----------------------------------------"
|
||||
read -p "Press Enter to continue..."
|
||||
kexec -l /mnt/iso/images/pxeboot/vmlinuz --initrd=/mnt/iso/images/pxeboot/initrd.img --append="inst.ks=file:///dev/disk/by-label/installer/ks.cfg inst.stage2=hd:LABEL=${ISO_LABEL} ${KERNEL_NET_PARAMS} inst.sshd inst.ssh.port=2222 inst.ssh.key=${SSH_KEY}"
|
||||
kexec -e
|
||||
echo -e "\n[+] Installation complete!"
|
||||
echo ""
|
||||
echo "IMPORTANT REMINDERS:"
|
||||
echo "1. Save your LUKS passphrase securely!"
|
||||
echo "2. After reboot, you'll need to enter it twice (once per disk)"
|
||||
echo "3. SSH to the server as user '$USERNAME'"
|
||||
echo ""
|
||||
echo "The system is ready for use!"
|
205
post-install.sh
Executable file
205
post-install.sh
Executable file
@ -0,0 +1,205 @@
|
||||
#!/bin/bash
|
||||
BANNER=$(cat << "EOF"
|
||||
:^7J5GB##&&##GPY?~:
|
||||
^75B&@@@@@@&&&@@@@@@@#GJ~:
|
||||
5&@@@&B5?7~^^^^^~!7YP#@@@@#!
|
||||
Y##P7^ :~JB#B!
|
||||
:: :
|
||||
7PP?: :^~!!~^: :?PP7
|
||||
:B@@B: !5B&@@@@&B5! :#@@B:
|
||||
:!!: ^G@@@&BPPB@@@@G^ :!!:
|
||||
:B@@@5^ ^5@@@B:
|
||||
:7J7: !@@@# :&@@@~ :?J7:
|
||||
J@@@5 :#@@@Y: :Y@@@B: 5@@@J
|
||||
!@@@&^ ~B@@@&G55G&@@@B~ ~&@@@~
|
||||
5@@@G: :7P#@@@@@@#P7: :B@@@Y
|
||||
:P@@@B~ :~!77!~: ~B@@@P
|
||||
Y@@@&Y^ ^5@@@@J
|
||||
!G@@@&P7^ ^7P&@@@G~
|
||||
!P&@@@&B? :: ?B&@@@&P!
|
||||
^75#&&Y :P&&5: 5&&B57^
|
||||
:^^ :P&&5: ^^:
|
||||
^^
|
||||
|
||||
[nullpoint]
|
||||
EOF
|
||||
)
|
||||
|
||||
TANG_SERVERS=(
|
||||
# "https://tang1.example.com your-thumbprint-1"
|
||||
# "https://tang2.example.com your-thumbprint-2"
|
||||
)
|
||||
TPM_PCR_BANK="sha256"
|
||||
TPM_PCR_IDS="0,1,2,3,4,5,6,7,8"
|
||||
ALMA_USER="null"
|
||||
ENABLE_MOTD=true
|
||||
# REQUIRED: Set your SSH public key here - installation will fail without it!
|
||||
SSH_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOkoTn2NreAXMriOUqzyj3YoFW6jMo9B5B+3R5k8yrMi dodox@dodox-ProArt"
|
||||
|
||||
########################################################
|
||||
# Config End
|
||||
########################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo -e "\n$BANNER"
|
||||
echo -e "\n[+] Starting post-installation configuration..."
|
||||
|
||||
# Check for SSH key
|
||||
if [ -z "${SSH_KEY:-}" ]; then
|
||||
echo "ERROR: No SSH key configured!"
|
||||
echo "You must set SSH_KEY variable at the top of this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for TPM
|
||||
echo "[+] Checking for TPM..."
|
||||
if [ ! -d "/sys/class/tpm/tpm0" ]; then
|
||||
echo "WARNING: No TPM detected!"
|
||||
TPM_ENABLED=false
|
||||
else
|
||||
echo "TPM detected."
|
||||
TPM_ENABLED=true
|
||||
fi
|
||||
|
||||
# Create user and add SSH key
|
||||
echo "[+] Creating user ${ALMA_USER}..."
|
||||
useradd -m -G wheel -s /bin/zsh ${ALMA_USER}
|
||||
mkdir -p /home/${ALMA_USER}/.ssh
|
||||
echo "${SSH_KEY}" > /home/${ALMA_USER}/.ssh/authorized_keys
|
||||
chmod 700 /home/${ALMA_USER}/.ssh
|
||||
chmod 600 /home/${ALMA_USER}/.ssh/authorized_keys
|
||||
chown -R ${ALMA_USER}:${ALMA_USER} /home/${ALMA_USER}/.ssh
|
||||
|
||||
# Install oh-my-zsh and powerlevel10k
|
||||
echo "[+] Installing oh-my-zsh and powerlevel10k..."
|
||||
# Run oh-my-zsh installer as the user
|
||||
sudo -u ${ALMA_USER} bash -c 'sh -c "$(wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)" "" --unattended'
|
||||
# Clone powerlevel10k theme
|
||||
sudo -u ${ALMA_USER} git clone --depth=1 https://github.com/romkatv/powerlevel10k.git /home/${ALMA_USER}/.oh-my-zsh/custom/themes/powerlevel10k
|
||||
|
||||
# Install dotfiles
|
||||
echo "[+] Setting up dotfiles..."
|
||||
if [ -d /tmp/nullpoint/dotfiles ]; then
|
||||
echo "[+] Installing dotfiles from repository..."
|
||||
cp /tmp/nullpoint/dotfiles/.* /home/${ALMA_USER}/ 2>/dev/null || true
|
||||
chown -R ${ALMA_USER}:${ALMA_USER} /home/${ALMA_USER}/
|
||||
else
|
||||
echo "[!] No dotfiles directory found, user will need to configure manually"
|
||||
fi
|
||||
|
||||
# Set up MOTD
|
||||
if [ "$ENABLE_MOTD" = true ]; then
|
||||
echo "[+] Setting up MOTD..."
|
||||
cat > /etc/motd << MOTD
|
||||
$BANNER
|
||||
MOTD
|
||||
fi
|
||||
|
||||
# Install additional packages
|
||||
echo "[+] Installing additional packages..."
|
||||
dnf install -y epel-release
|
||||
dnf config-manager --set-enabled crb
|
||||
dnf install -y \
|
||||
clevis clevis-luks clevis-tang clevis-tpm2 tpm2-tools tpm2-tss \
|
||||
git zsh tmux neovim python3-pip \
|
||||
dracut-clevis dropbear tree curl wget nano
|
||||
|
||||
# Install lsd and bat from GitHub releases (not in repos)
|
||||
echo "[+] Installing lsd and bat..."
|
||||
# Get latest lsd version
|
||||
LSD_VERSION=$(curl -s https://api.github.com/repos/lsd-rs/lsd/releases/latest | grep -Po '"tag_name": "v\K[0-9.]+')
|
||||
curl -sL "https://github.com/lsd-rs/lsd/releases/download/v${LSD_VERSION}/lsd-v${LSD_VERSION}-x86_64-unknown-linux-musl.tar.gz" | tar xz -C /tmp
|
||||
mv /tmp/lsd-*/lsd /usr/local/bin/
|
||||
chmod +x /usr/local/bin/lsd
|
||||
|
||||
# Get latest bat version
|
||||
BAT_VERSION=$(curl -s https://api.github.com/repos/sharkdp/bat/releases/latest | grep -Po '"tag_name": "v\K[0-9.]+')
|
||||
curl -sL "https://github.com/sharkdp/bat/releases/download/v${BAT_VERSION}/bat-v${BAT_VERSION}-x86_64-unknown-linux-musl.tar.gz" | tar xz -C /tmp
|
||||
mv /tmp/bat-*/bat /usr/local/bin/
|
||||
chmod +x /usr/local/bin/bat
|
||||
|
||||
# Create batman script for fancy man pages
|
||||
cat > /usr/local/bin/batman << 'BATMAN'
|
||||
#!/bin/bash
|
||||
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
||||
export MANROFFOPT="-c"
|
||||
man "$@"
|
||||
BATMAN
|
||||
chmod +x /usr/local/bin/batman
|
||||
|
||||
# Create .tmp directory for user
|
||||
mkdir -p /home/${ALMA_USER}/.tmp
|
||||
chown ${ALMA_USER}:${ALMA_USER} /home/${ALMA_USER}/.tmp
|
||||
|
||||
# Configure Clevis for automatic unlock
|
||||
if [ ${#TANG_SERVERS[@]} -gt 0 ] || [ "$TPM_ENABLED" = true ]; then
|
||||
echo "[+] Configuring Clevis for automatic unlock..."
|
||||
|
||||
# Find LUKS devices
|
||||
LUKS_DEVICES=$(lsblk -o NAME,FSTYPE -nr | grep crypto_LUKS | cut -d' ' -f1)
|
||||
|
||||
for device in $LUKS_DEVICES; do
|
||||
DEVICE_PATH="/dev/${device}"
|
||||
echo "Configuring Clevis for ${DEVICE_PATH}..."
|
||||
|
||||
if [ "$TPM_ENABLED" = true ] && [ ${#TANG_SERVERS[@]} -eq 0 ]; then
|
||||
# TPM only
|
||||
clevis luks bind -d "$DEVICE_PATH" tpm2 "{\"pcr_bank\":\"$TPM_PCR_BANK\",\"pcr_ids\":\"$TPM_PCR_IDS\"}"
|
||||
elif [ "$TPM_ENABLED" = false ] && [ ${#TANG_SERVERS[@]} -gt 0 ]; then
|
||||
# Tang only
|
||||
for server in "${TANG_SERVERS[@]}"; do
|
||||
read -r url thumbprint <<< "$server"
|
||||
clevis luks bind -d "$DEVICE_PATH" tang "{\"url\":\"$url\",\"thp\":\"$thumbprint\"}"
|
||||
done
|
||||
elif [ "$TPM_ENABLED" = true ] && [ ${#TANG_SERVERS[@]} -gt 0 ]; then
|
||||
# Both TPM and Tang (require both)
|
||||
CONFIG="{\"t\":2,\"pins\":{"
|
||||
CONFIG+="\"tpm2\":{\"pcr_bank\":\"$TPM_PCR_BANK\",\"pcr_ids\":\"$TPM_PCR_IDS\"},"
|
||||
CONFIG+="\"tang\":{\"t\":1,\"tang\":["
|
||||
for server in "${TANG_SERVERS[@]}"; do
|
||||
read -r url thumbprint <<< "$server"
|
||||
CONFIG+="{\"url\":\"$url\",\"thp\":\"$thumbprint\"},"
|
||||
done
|
||||
CONFIG="${CONFIG%,}]}}}"
|
||||
clevis luks bind -d "$DEVICE_PATH" sss "$CONFIG"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Enable Clevis for early boot
|
||||
echo "[+] Enabling Clevis for early boot..."
|
||||
systemctl enable clevis-luks-askpass.service
|
||||
|
||||
# Configure dropbear for remote unlock
|
||||
echo "[+] Configuring dropbear for remote unlock..."
|
||||
mkdir -p /etc/dropbear
|
||||
echo "${SSH_KEY}" > /etc/dropbear/authorized_keys
|
||||
chmod 600 /etc/dropbear/authorized_keys
|
||||
|
||||
# Regenerate initramfs
|
||||
echo "[+] Regenerating initramfs..."
|
||||
dracut -f --regenerate-all
|
||||
|
||||
# Enable required services
|
||||
echo "[+] Enabling services..."
|
||||
# systemctl enable stratisd # Not needed without Stratis
|
||||
systemctl enable sshd
|
||||
|
||||
# Disable root login
|
||||
echo "[+] Securing SSH..."
|
||||
sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
|
||||
|
||||
# Set SELinux to enforcing
|
||||
echo "[+] Setting SELinux to enforcing..."
|
||||
sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
|
||||
|
||||
echo "✅ Post-installation complete!"
|
||||
echo ""
|
||||
echo "IMPORTANT: The LUKS passphrase is set in install.conf"
|
||||
echo "Save it securely for recovery purposes."
|
||||
echo ""
|
||||
echo "After reboot:"
|
||||
echo "- System will unlock automatically if TPM/Tang configured"
|
||||
echo "- Or SSH to port 22 for manual unlock"
|
||||
echo "- Then SSH as user '${ALMA_USER}'"
|
Loading…
Reference in New Issue
Block a user