Compare commits
27 Commits
def3a3a87d
...
91bd01472b
| Author | SHA1 | Date | |
|---|---|---|---|
|
91bd01472b
|
|||
|
5b13b2259c
|
|||
|
906e56f34c
|
|||
|
dd5f543db2
|
|||
|
f33009d480
|
|||
|
9d35d04990
|
|||
|
c00c9aed16
|
|||
|
5f4873fec5
|
|||
|
44cbac7a98
|
|||
|
cbebcb4fdc
|
|||
|
974ac84cbc
|
|||
|
4bc128cdec
|
|||
|
cc8e051501
|
|||
|
616ac6a2a8
|
|||
|
ce35cd1838
|
|||
|
70871b8944
|
|||
|
995659730f
|
|||
|
4136515526
|
|||
|
e58202c37e
|
|||
|
aee3437156
|
|||
|
c3d4109114
|
|||
|
7e7628a0e3
|
|||
|
5022a3de7d
|
|||
|
0479274245
|
|||
|
4a25476fd6
|
|||
|
cc7d907d6d
|
|||
| a7c18c5ca8 |
42
Makefile
42
Makefile
@@ -7,12 +7,12 @@ FZF != command -v sk || command -v fzy || command -v fzf || \
|
||||
ifeq "$(FZF)" "/usr/bin/fzy"
|
||||
FZF += -i
|
||||
else
|
||||
FZF += --print-query | cat
|
||||
FZF += --print-query | tail -1
|
||||
endif
|
||||
|
||||
spill_contents = sed -e '1,/---/d'
|
||||
|
||||
help: .git/info/exclude ## Print the help message
|
||||
help: ## Print the help message
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[0-9a-zA-Z._-]+:.*?## / {printf "\033[36m%s\033[0m : %s\n", $$1, $$2}' $(MAKEFILE_LIST) | \
|
||||
sort | \
|
||||
column -s ':' -t
|
||||
@@ -32,8 +32,11 @@ $(foreach dir, $(categories), \
|
||||
$(eval .dbs/$(dir).rec: $(wildcard $(dir)/*)) \
|
||||
)
|
||||
|
||||
.dbs/:
|
||||
%/:
|
||||
mkdir $@
|
||||
echo '*' > $@.gitignore
|
||||
|
||||
include cmd.mk
|
||||
|
||||
$(databases): .dbs/%.rec: %/ | .dbs/
|
||||
$(info making $(@F))
|
||||
@@ -73,18 +76,6 @@ default += .git/info/exclude
|
||||
.PHONY: database
|
||||
database: $(default) ## Make a recfiles database
|
||||
|
||||
.PHONY: article
|
||||
article: ## Write an article
|
||||
@path=$$(find $(categories) -type d | sort | uniq | $(FZF)) ;\
|
||||
read -p "Title: " title ;\
|
||||
filename="$$(echo "$$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '_')" ;\
|
||||
mkdir -p $$path ;\
|
||||
printf '%s\n' '---' >> $$path/$$filename.md ;\
|
||||
printf 'title: "%s"\n' "$$title" >> $$path/$$filename.md ;\
|
||||
printf 'tags: [ "%s" ]\n' "$$path" | tr '[:upper:]' '[:lower:]' | sed 's#\/#", "#g' >> $$path/$$filename.md ;\
|
||||
printf '%s\n\n' '---' >> $$path/$$filename.md ;\
|
||||
$(EDITOR) +5 "$$path/$$filename.md"
|
||||
|
||||
.dbs/map.fmt:| .dbs/
|
||||
printf '%s\n' '[ {{requires[0]}} ] --> [ {{title}} ] {border-style: dashed;}' > $@
|
||||
printf '%s\n' '[ {{requires[1]}} ] --> [ {{title}} ] {border-style: dashed;}' >> $@
|
||||
@@ -100,3 +91,24 @@ map: db.rec .dbs/map.fmt ## Show knowledge dependency map
|
||||
.PHONY: clean
|
||||
clean: ## Remove all generated files
|
||||
$(RM) $(default)
|
||||
|
||||
.PHONY: article
|
||||
article: **/ **/**/ ## Write a new article
|
||||
category=$(shell echo $^ | tr ' ' '\n' | $(FZF) ) \
|
||||
&& read -p "Article title? " name \
|
||||
&& filename="$$(echo "$$name" \
|
||||
| cut -d: -f1 \
|
||||
| tr -cd '[:alpha:]' | tr '[A-Z ]' '[a-z_]' )" \
|
||||
&& $(MAKE) -e TITLE="$$name" "$$category"/"$$filename.md"
|
||||
|
||||
%.md:
|
||||
[ -d "$(@D)" ] || mkdir $(@D)
|
||||
printf '%s\n' '---' >> $@
|
||||
printf 'title: %s\n' '$(TITLE)' >> $@
|
||||
tags="$$(echo $(@D) | sed 's#/$$#"# ; s#/#", "#g ; s#^#"#' )" \
|
||||
&& printf 'tags [ %s ]\n' "$$tags" >> $@
|
||||
printf '%s\n\n' '---' >> $@
|
||||
$(EDITOR) +5 $@
|
||||
git add $@
|
||||
git commit -m"article: $(TITLE)"
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: "column"
|
||||
tags: [ "basics", "format", "json" ]
|
||||
---
|
||||
|
||||
Put output into column.
|
||||
|
||||
```sh
|
||||
du -h /etc/* | column
|
||||
```
|
||||
|
||||
Reformat file with an explicit separator (`-s`):
|
||||
|
||||
```sh
|
||||
column -ts: /etc/passwd
|
||||
```
|
||||
|
||||
Give columns names (`-N`), so you can hide some (`-H`):
|
||||
|
||||
```sh
|
||||
column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID /etc/passwd
|
||||
```
|
||||
|
||||
Reorder with `-O` (unspecified items remain):
|
||||
|
||||
|
||||
```sh
|
||||
column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID -O User,Description,shell /etc/passwd
|
||||
```
|
||||
|
||||
Output to json format with `-J`:
|
||||
|
||||
```sh
|
||||
column -J -ts: -H PW,GID,shell -N User,PW,UID,GID,Description,Home,shell /etc/passwd
|
||||
```
|
||||
|
||||
@@ -5,6 +5,7 @@ tags: [ "fun" ]
|
||||
|
||||
- `asciiquarium`
|
||||
- `cbonsai -lim "$(fortune)"`
|
||||
- `printf 'w\na\n' | ssh -tt nethack@alt.org`
|
||||
|
||||
```sh
|
||||
cow=$(cowsay -l | sort -R | head -1)
|
||||
|
||||
@@ -30,6 +30,11 @@ Done
|
||||
- If you have a command, Control + d will execute the command.
|
||||
- If you have nothing, `exit`.
|
||||
|
||||
Clear Search Highlights
|
||||
=======================
|
||||
|
||||
`<Esc>+u`
|
||||
|
||||
Input Run-Commands (`~/.inputrc`)
|
||||
=================================
|
||||
|
||||
|
||||
25
cmd.mk
Normal file
25
cmd.mk
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
cmds != recsel command.rec -t command -G bin -U -CP bin
|
||||
lists = $(patsubst %,lists/%.md, $(cmds))
|
||||
|
||||
default += $(lists)
|
||||
|
||||
get_title = printf 'title: "%s"\n' '${1}'
|
||||
get_tags = recsel -t $(basename $<) $< -G bin \
|
||||
-e 'bin = "$(1)"' -U -CP tag | \
|
||||
sed 's/.*/"&",/g' | \
|
||||
tr '\n' ' ' | \
|
||||
sed 's/.*/tags: [ &]/'
|
||||
|
||||
list_commands = recsel -t $(basename $<) $< -e 'bin = "$(1)"' | \
|
||||
recfmt -f lists.fmt
|
||||
|
||||
lists/%.md: command.rec | lists/
|
||||
@printf '%s\n' '---' > $@
|
||||
@$(call get_title,$(basename $(notdir $@))) >> $@
|
||||
@$(call get_tags,$(basename $(notdir $@))) >> $@
|
||||
@printf '\n%s\n' '---' >> $@
|
||||
@$(call list_commands,$(basename $(notdir $@))) >> $@
|
||||
|
||||
.PHONY: cmd
|
||||
cmd: $(lists) ## Big lists of commands
|
||||
51
command.rec
Normal file
51
command.rec
Normal file
@@ -0,0 +1,51 @@
|
||||
%rec: command
|
||||
%doc: shell command examples
|
||||
%type: aim line
|
||||
%allowed: aim cmd bin tag
|
||||
|
||||
aim: Put output into column
|
||||
cmd: du -h /etc/* | column
|
||||
bin: column
|
||||
tag: format
|
||||
|
||||
aim: Reformat file with an explicit separator (`-s`)
|
||||
cmd: column -ts: /etc/passwd
|
||||
bin: column
|
||||
tag: format
|
||||
|
||||
aim: Give columns names (`-N`), so you can hide some (`-H`)
|
||||
cmd: column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID /etc/passwd
|
||||
bin: column
|
||||
tag: format
|
||||
|
||||
aim: Reorder with `-O` (unspecified items remain)
|
||||
cmd: column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID -O User,Description,shell /etc/passwd
|
||||
bin: column
|
||||
tag: format
|
||||
|
||||
aim: Output to json format with `-J`
|
||||
cmd: column -J -ts: -H PW,GID,shell -N User,PW,UID,GID,Description,Home,shell /etc/passwd
|
||||
bin: column
|
||||
tag: format
|
||||
tag: json
|
||||
|
||||
aim: Make a QR Code image:
|
||||
cmd: qrencode 'https://play.google.com/store/apps/details?id=org.briarproject.briar.android' -o "$FILE".png
|
||||
bin: qrencode
|
||||
tag: qr
|
||||
|
||||
aim: Make a QR Coded message in the terminal:
|
||||
cmd: qrencode -t ansi "Hello World"
|
||||
bin: qrencode
|
||||
tag: qr
|
||||
|
||||
aim: Read a QR Code image:
|
||||
cmd: zbarimg $FILE
|
||||
bin: qrencode
|
||||
tag: qr
|
||||
|
||||
aim: Show wifi QR code (only with Network Manager):
|
||||
cmd: nmcli device wifi show-password
|
||||
bin: qrencode
|
||||
tag: qr
|
||||
tag: wifi
|
||||
@@ -129,7 +129,7 @@ Refreshing keys will tell you if some key you have contains a signature from som
|
||||
gpg --refresh-keys
|
||||
```
|
||||
|
||||
You can use the [crontab](../../basics/cron.md) to refresh keys, but this will mostly fail, since keyservers often don't hold the right data.
|
||||
You can use the [crontab](../../system/cron.md) to refresh keys, but this will mostly fail, since keyservers often don't hold the right data.
|
||||
|
||||
# Export
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Interactive String Substitution"
|
||||
tags: [ "data", "vim", "substitution" ]
|
||||
tags: [ "data", "vim", "substitution", "replace", "TUI" ]
|
||||
---
|
||||
|
||||
Want to find and replace, but also confirm each instance?
|
||||
|
||||
@@ -44,11 +44,24 @@ You can get an RSS feed from any YouTube video with this script:
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
CHANNEL_ID="$(curl -s "$1" | tr ',' '\n' | grep -Po 'channelId":"\K[\w+-]+' | tail -1)"
|
||||
FEED_URL="https://www.youtube.com/feeds/videos.xml?channel_id=$CHANNEL_ID"
|
||||
CHANNEL_NAME="$(curl -s "$FEED_URL" | grep -m 1 -Po 'title\>\K[\w\s]+')"
|
||||
set -e
|
||||
|
||||
printf '%s "%s"\n' "$FEED_URL" "$CHANNEL_NAME"
|
||||
db=~/rec/feeds.rec
|
||||
|
||||
rec="${2:-$db}"
|
||||
|
||||
[ ! -z "$1" ] || {
|
||||
echo "Give me a youtube URL"
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -w "$rec" ] || touch "$rec"
|
||||
|
||||
CHANNEL_ID="$(curl -s "$1" | tr ',' '\n' | grep -Po 'channelId":"\K[\w+-]+' | tail -1)"
|
||||
URL="https://www.youtube.com/feeds/videos.xml?channel_id=$CHANNEL_ID"
|
||||
Name="$(curl -s "$URL" | grep -m 1 -Po 'title\>\K[\w\s]+')"
|
||||
|
||||
recins --verbose -t Feed -f Name -v "${Name}" -f URL -v "${URL}" -f Category -v Videos -f Rating -v 3 -f Working -v yes "$rec"
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "pass"
|
||||
tags: [ "data" ]
|
||||
tags: [ "data", "credentials", "secrets" ]
|
||||
requires: "GPG Basics"
|
||||
---
|
||||
|
||||
@@ -28,7 +28,7 @@ To add a basic password, e.g. for `$WEBSITE`:
|
||||
pass $WEBSITE
|
||||
```
|
||||
|
||||
To insert a multiline password, e.g. with a login name:
|
||||
To insert a multi-line password, e.g. with a login name:
|
||||
|
||||
```sh
|
||||
pass add -m $WEBSITE
|
||||
|
||||
48
data/pass_otp.md
Normal file
48
data/pass_otp.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "pass with otp"
|
||||
tags: [ "data", "credentials", "secrets", "2fa", "otp" ]
|
||||
requires: "pass"
|
||||
---
|
||||
|
||||
Need a Microsoft or Google authenticator?
|
||||
No you don't.
|
||||
|
||||
These usually come in the form of QR codes.
|
||||
|
||||
|
||||
```qr code
|
||||
|
||||
|
||||
█▀▀▀▀▀█ ▀ ▀▀▀ ▀ ▄ █▀▀▀▀▀█
|
||||
█ ███ █ ▄▄▀▄▄▀▄▄▀ █ ███ █
|
||||
█ ▀▀▀ █ ██ ▀▄██▀▀ █ ▀▀▀ █
|
||||
▀▀▀▀▀▀▀ █ █▄▀ █ █ ▀▀▀▀▀▀▀
|
||||
█▄▄ █▄▀▀██ ▄▄▀▀▄██▀▀██ ▄▀
|
||||
▄██▄▀█▀█ ▀▄▀ █▀▀▀█ ▀▀▀█▄
|
||||
▄ ▄▄█ ▀▀ ▄▄▀▀█▄█ ▀▀ ▄▀▀█▀
|
||||
█ ▀ ▀▀█▀▀ ▄ ▄█▀▄▀██▀█▄
|
||||
▀▀▀ ▀ ▀ █▄▄▀▄▀▀▄█▀▀▀█▀▀
|
||||
█▀▀▀▀▀█ ▀▄ █▀█▀ █ ▀ █▄▄
|
||||
█ ███ █ ▀ ▄ ▀█▄ ████▀▀█▄█
|
||||
█ ▀▀▀ █ ▄▀ ▄ ▄▄ ██▄▄█▄█
|
||||
▀▀▀▀▀▀▀ ▀ ▀▀ ▀▀▀ ▀▀ ▀▀▀
|
||||
|
||||
|
||||
```
|
||||
|
||||
Download the code, and get the information out:
|
||||
|
||||
|
||||
```sh
|
||||
zbarimg qr.png
|
||||
otp="$(zbarimg qr.png | sed 's/QR-Code://')"
|
||||
otp_name=site.org.otp
|
||||
echo "${otp}" | pass otp add --echo "${otp_name}"
|
||||
```
|
||||
|
||||
Show the OTP:
|
||||
|
||||
|
||||
```sh
|
||||
pass otp "${otp_name}"
|
||||
```
|
||||
@@ -43,8 +43,8 @@ recset -f "$new_field" --delete $database
|
||||
```
|
||||
|
||||
- [Extended example](recfiles/extended.md)
|
||||
- [Playing with board games data](recfiles/Board_Games.md)
|
||||
- [Playing with IP addresses](recfiles/IP_ASN.md)
|
||||
- [Playing with board games data](recfiles/board_games.md)
|
||||
- [Playing with IP addresses](recfiles/ip_asn.md)
|
||||
- [Manage LaTeX Bibliographies](recfiles/bibliography.md)
|
||||
- [Fixes](recfiles/recfixes.md)
|
||||
|
||||
|
||||
65
data/recfiles/nginx_logs.md
Normal file
65
data/recfiles/nginx_logs.md
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: "nginx logs with recfiles"
|
||||
tags: [ "data", "recfiles", "logs" ]
|
||||
requires: [ "Recfiles", "nginx" ]
|
||||
---
|
||||
|
||||
The standard `nginx` log format has such a lack of consistency or meaning that you might squint your face into a whirlpool making sense of them:
|
||||
|
||||
|
||||
```nonsense
|
||||
18.97.14.85 - - [16/Nov/2025:00:52:12 +0100] "GET /posts/learning_without_experts/content.html HTTP/1.1" 200 1704 "-" "CCBot/2.0 (https://commoncrawl.org/faq/)"
|
||||
57.141.0.25 - - [16/Nov/2025:00:52:18 +0100] "GET /posts/hope_you_win/ HTTP/1.1" 200 61997 "-" "meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)"
|
||||
201.17.157.249 - - [16/Nov/2025:00:52:19 +0100] "GET https://ttrpgs.com/post/wp/ HTTP/1.1" 200 45202 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
47.246.164.151 - - [16/Nov/2025:00:52:22 +0100] "GET https://ttrpgs.com/css/styles.dc38388a8f0b890e788bd3a99b7495d14e7d5ac4359ed3b49abeb778497863b284ad4cc7e496ef58c84139295f9bafed82f5a41345eda86bd2d429cccb7c2596.css HTTP/1.1" 200 27109 "https://ttrpgs.com/post/wp/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
47.246.164.154 - - [16/Nov/2025:00:52:22 +0100] "GET https://ttrpgs.com/fonts/Metropolis-MediumItalic.woff2 HTTP/1.1" 200 28100 "https://ttrpgs.com/css/styles.dc38388a8f0b890e788bd3a99b7495d14e7d5ac4359ed3b49abeb778497863b284ad4cc7e496ef58c84139295f9bafed82f5a41345eda86bd2d429cccb7c2596.css" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
47.246.164.135 - - [16/Nov/2025:00:52:22 +0100] "GET https://ttrpgs.com/fonts/Metropolis-Regular.woff2 HTTP/1.1" 200 24152 "https://ttrpgs.com/css/styles.dc38388a8f0b890e788bd3a99b7495d14e7d5ac4359ed3b49abeb778497863b284ad4cc7e496ef58c84139295f9bafed82f5a41345eda86bd2d429cccb7c2596.css" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
```
|
||||
|
||||
Someone created this logging format on purpose, to make sure nobody could parse it with a hundred `column`, `cut`, or `awk` pipes.
|
||||
|
||||
The problem lies in `/etc/nginx/nginx.conf`:
|
||||
|
||||
|
||||
```conf
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
```
|
||||
|
||||
Despite a request of three strings, this format returns one string.
|
||||
|
||||
It can output to recfile format like this:
|
||||
|
||||
|
||||
```conf
|
||||
log_format main '\nIP: $remote_addr\n'
|
||||
'User: $remote_user\n'
|
||||
'Date: $time_local\n'
|
||||
'Request: $request\n'
|
||||
'Status: $status\n'
|
||||
'Bytes: $body_bytes_sent\n'
|
||||
'Referrer: $http_referer\n'
|
||||
'Agent: $http_user_agent\n'
|
||||
'XForward: $http_x_forwarded_for\n';
|
||||
|
||||
access_log /var/log/nginx/access.rec main;
|
||||
```
|
||||
|
||||
Note the newline (`\n`) symbol, required to start a new entry on a new line.
|
||||
|
||||
1. `cp /etc/nginx.conf /etc/nginx.conf.bak`
|
||||
1. Change `/etc/nginx.conf` to match the format above.
|
||||
1. Check the file works with `nginx -t`.
|
||||
1. Restart the `nginx` service.
|
||||
1. Access that web page to make sure that at least one log exists.
|
||||
1. Check the file with `recfix /var/log/nginx/access.rec`.
|
||||
|
||||
Once it works, you can add the usual recfile headers:
|
||||
|
||||
|
||||
```sh
|
||||
sed -i '1 i \ ' /var/log/nginx/access.rec
|
||||
sed -i '1 i %rec: Weblog' /var/log/nginx/access.rec
|
||||
sed -i '2 i %doc: nginx access logs' /var/log/nginx/access.rec
|
||||
```
|
||||
@@ -36,7 +36,7 @@ git clone http://localhost:23232/${some_repo}.git
|
||||
|
||||
### `https` Setup
|
||||
|
||||
Put this file at `/etc/nginx/sites-enabled/$DOMAIN.tld`, then set up standard certificates with [nginx](../networking/website/nginx.md).
|
||||
Put this file at `/etc/nginx/sites-enabled/$DOMAIN.tld`, then set up standard certificates with [nginx](../../networking/website/nginx.md).
|
||||
|
||||
(replace `${DOMAIN_NAME}` with your domain's name).
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ vi /etc/locale.gen
|
||||
locale-gen
|
||||
```
|
||||
|
||||
Make your keyboard changes permenent with:
|
||||
Make your keyboard changes permanent with:
|
||||
|
||||
```sh
|
||||
vi /etc/vconsole.conf
|
||||
|
||||
@@ -6,8 +6,9 @@ requirements: [ "pacman" ]
|
||||
|
||||
```sh
|
||||
pacman --sync --noconfirm --needed base-devel gcc git
|
||||
git clone https://aur.archlinux.org/yay.git /tmp/yay
|
||||
makepkg -C !$ -si
|
||||
git clone https://aur.archlinux.org/yay.git
|
||||
cd yay
|
||||
makepkg -si
|
||||
```
|
||||
|
||||
The flags are mostly the same as in `pacman`.
|
||||
|
||||
@@ -22,6 +22,12 @@ Search with regex:
|
||||
xbps-query --regex -Rs 'cow(s)?\w'
|
||||
```
|
||||
|
||||
Search for `genfstab`:
|
||||
|
||||
```sh
|
||||
xlocate genfstab
|
||||
```
|
||||
|
||||
List what's required for cowsay
|
||||
|
||||
```sh
|
||||
|
||||
@@ -5,9 +5,17 @@ tags: [ "networking" ]
|
||||
|
||||
# Get a Hostname
|
||||
|
||||
[onion hidden service guide](https://community.torproject.org/onion-services/setup/)
|
||||
|
||||
```sh
|
||||
sudo vim /etc/tor/torrc
|
||||
```
|
||||
|
||||
Uncomment the lines about `/var/lib/tor/hidden_services`, including port 22 (or whatever); restart tor, then go to that directory, and cat the hostname.
|
||||
|
||||
|
||||
# SSH over tor
|
||||
|
||||
install package `torsocks`, and add it before `ssh` command, for easier use, add it to `.ssh/config`
|
||||
|
||||
`torsocks ssh user@{someonionhash}.onion`
|
||||
|
||||
@@ -48,7 +48,7 @@ echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/wg.conf
|
||||
```
|
||||
|
||||
```sh
|
||||
systemctl enable --now wg-quiqck@wg0
|
||||
systemctl enable --now wg-quick@wg0
|
||||
```
|
||||
|
||||
```sh
|
||||
@@ -67,7 +67,7 @@ Be root.
|
||||
|
||||
Install `wireguard-tools` on the client.
|
||||
|
||||
Copy the client private key and server public key to the server (or just fill in the variables).
|
||||
Copy the client server public key to the server (or just fill in the variables).
|
||||
|
||||
|
||||
```sh
|
||||
|
||||
83
sound/mpd_pipewire.md
Normal file
83
sound/mpd_pipewire.md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: "mpd with pipewire"
|
||||
tags: [ "sound", "pipewire" ]
|
||||
requirements: [ "pipewire" ]
|
||||
---
|
||||
# Setup
|
||||
|
||||
## Configuration
|
||||
|
||||
This is a minimum configuration file for /etc/mpd.conf
|
||||
|
||||
> music_directory "/var/lib/mpd/music"
|
||||
>
|
||||
> playlist_directory "/var/lib/mpd/playlists"
|
||||
>
|
||||
> db_file "/var/lib/mpd/mpd.db"
|
||||
>
|
||||
>
|
||||
> pid_file "/run/mpd/mpd.pid"
|
||||
>
|
||||
> state_file "/var/lib/mpd/mpdstate"
|
||||
>
|
||||
>
|
||||
> user "mpd"
|
||||
>
|
||||
> audio_output {
|
||||
> type "pulse"
|
||||
> name "My Pulse Output"
|
||||
> }
|
||||
>
|
||||
|
||||
## Set Pulseaudio to Run System-Wide
|
||||
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/pipewire/pipewire-pulse.conf.d
|
||||
|
||||
cat > /etc/pipewire/pipewire-pulse.conf.d/pulse-server.conf << "EOF"
|
||||
pulse.properties = {
|
||||
server.address = [
|
||||
"unix:native"
|
||||
"tcp:4713" # IPv4 and IPv6 on all addresses
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
```
|
||||
|
||||
Give `mpd` access to pulse:
|
||||
|
||||
```sh
|
||||
grep pulse /etc/group | cut -d: -f1
|
||||
|
||||
grep pulse /etc/group | cut -d: -f1 | while read g; do
|
||||
sudo usermod -aG $g mpd
|
||||
done
|
||||
```
|
||||
|
||||
Working with mpd will be easier if you have access to its files, so maybe:
|
||||
|
||||
```sh
|
||||
sudo usermod -aG mpd $USER
|
||||
```
|
||||
|
||||
Remember to reboot.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
Check pulse is working.
|
||||
|
||||
```sh
|
||||
ss | grep 4713
|
||||
```
|
||||
|
||||
# Notifications (AUR)
|
||||
|
||||
Install `mpd-notification` and then start the service:
|
||||
|
||||
```sh
|
||||
systemctl --user enable mpd-notification
|
||||
```
|
||||
|
||||
12
sound/pipewire.md
Normal file
12
sound/pipewire.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "pipewire"
|
||||
tags: [ "sound" ]
|
||||
---
|
||||
|
||||
Install `wireplumber` and `pipewire`, then add your user to any `pipewire` group.
|
||||
|
||||
```sh
|
||||
sudo ln -s /usr/share/examples/pipewire/20-pipewire-pulse.conf /etc/pipewire/pipewire.conf.d/20-pipewire-pulse.conf
|
||||
|
||||
sudo ln -s /usr/share/examples/wireplumber/10-wireplumber.conf /etc/pipewire/pipewire.conf.d/10-wireplumber.conf
|
||||
```
|
||||
@@ -14,12 +14,27 @@ Say 'hello' to yourself:
|
||||
ansible --module-name=ping localhost
|
||||
```
|
||||
|
||||
Ansible takes a lot of information about each machine during setup:
|
||||
|
||||
```sh
|
||||
TMP=$(mktemp)
|
||||
ansible --module-name=setup localhost | tee $TMP
|
||||
less !$
|
||||
```
|
||||
|
||||
If you have `jq`, you can pull out info:
|
||||
|
||||
```sh
|
||||
sed -i 's/.*SUCC.*/{/' $TMP
|
||||
jq '.ansible_facts.ansible_distribution' < $TMP
|
||||
```
|
||||
|
||||
Upgrade through the package manager.
|
||||
|
||||
`packager=apt` (or `pacman` or `xbps`,...)
|
||||
|
||||
```sh
|
||||
packager=apt
|
||||
packager="$( jq -r '.ansible_facts.ansible_pkg_mgr' < $TMP )"
|
||||
ansible --module-name=${packager} --args "upgrade=yes" localhost
|
||||
```
|
||||
|
||||
@@ -87,4 +102,8 @@ ansible-inventory --list -y -i
|
||||
ansible-vault view sec.yml --vault-pass-file pass.sh
|
||||
```
|
||||
|
||||
community.general.say voice=en_GB msg="Testing 123"
|
||||
Install `espeak', then make the computer say something:
|
||||
|
||||
```sh
|
||||
ansible --module-name=say --args "msg='testing'" localhost
|
||||
```
|
||||
|
||||
@@ -178,6 +178,6 @@ In this case, the makefile can see that `backup` depends on the current backup f
|
||||
|
||||
# The Rest
|
||||
|
||||
- [File patterns](Makefiles/patterns.md)
|
||||
- [Makefile graphs](Makefiles/graph-easy.md)
|
||||
- [In-build help](Makefiles/help.md)
|
||||
- [File patterns](makefiles/patterns.md)
|
||||
- [Makefile graphs](makefiles/graph-easy.md)
|
||||
- [In-build help](makefiles/help.md)
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Makefile Patterns"
|
||||
tags: [ "system", "make" ]
|
||||
---
|
||||
|
||||
Using the [basic example](../Makefile.md), you can make a complete backup of all backup files.
|
||||
Using the [basic example](../makefiles.md), you can make a complete backup of all backup files.
|
||||
This file will depend upon everything inside the `$(storage_directory)`.
|
||||
Unlike `bash`, you can't just say `storage_directory/*`: the pattern must be stated as a 'wildcard'.
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
title: "QR Codes"
|
||||
tags: [ "qrencode", "zbar" ]
|
||||
---
|
||||
|
||||
Make a QR Code image:
|
||||
|
||||
```sh
|
||||
qrencode 'https://play.google.com/store/apps/details?id=org.briarproject.briar.android' -o "$FILE".png
|
||||
```
|
||||
|
||||
Make a QR Coded message in the terminal:
|
||||
|
||||
```sh
|
||||
qrencode -t ansi "Hello World"
|
||||
```
|
||||
|
||||
Read a QR Code image:
|
||||
|
||||
```sh
|
||||
zbarimg $FILE
|
||||
```
|
||||
|
||||
Show wifi QR code (only with Network Manager):
|
||||
|
||||
```sh
|
||||
nmcli device wifi show-password
|
||||
```
|
||||
71
vision/record_terminal.md
Normal file
71
vision/record_terminal.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "Record a Terminal Session"
|
||||
tags: [ "vision", "share" ]
|
||||
---
|
||||
|
||||
Record a terminal command, then press 'Control + d' to exit.
|
||||
|
||||
```sh
|
||||
script --timing=time.log stat.txt
|
||||
ls -a
|
||||
ls -al
|
||||
stat ~/.bashrc
|
||||
^D
|
||||
```
|
||||
|
||||
Replay the session:
|
||||
|
||||
```sh
|
||||
scriptreplay --timing=time.log stat.txt
|
||||
```
|
||||
|
||||
Try a bare command, without any timing:
|
||||
|
||||
```sh
|
||||
script -c 'top | lolcat' loltop
|
||||
nl loltop
|
||||
```
|
||||
|
||||
Has your terminal messed up?
|
||||
Is the cursor hiding?
|
||||
Reset it!
|
||||
|
||||
```sh
|
||||
reset
|
||||
```
|
||||
If you can't see any keys, keep typing anyway: have faith in your terminal.
|
||||
|
||||
This `loltop` file will not play properly as it has no timings file.
|
||||
But you can cheat the system and use your other timings file:
|
||||
|
||||
```sh
|
||||
scriptreplay --timing=time.log loltop
|
||||
```
|
||||
|
||||
This will mostly not work well, but it shows how the timing file works:
|
||||
|
||||
|
||||
```text
|
||||
0.033401 23
|
||||
0.044513 8
|
||||
0.000016 219
|
||||
1.349324 114
|
||||
0.179106 1
|
||||
0.088790 1
|
||||
0.072821 1
|
||||
0.358337 2
|
||||
0.000254 9
|
||||
0.004720 52
|
||||
0.000084 21
|
||||
0.155462 671
|
||||
```
|
||||
|
||||
I think it works like this?
|
||||
|
||||
| How long it took | to type *n* characters |
|
||||
|:----------------:|:----------------------:|
|
||||
| 0.033401 | 23 |
|
||||
| 0.044513 | 8 |
|
||||
| 0.000016 | 219 |
|
||||
| 1.349324 | 114 |
|
||||
|
||||
260
writing/ed.md
Normal file
260
writing/ed.md
Normal file
@@ -0,0 +1,260 @@
|
||||
---
|
||||
title: "Ed: The Standard Editor"
|
||||
tags: [ "writing", "guide" ]
|
||||
---
|
||||
|
||||
`ed` was designed for real terminals, i.e. a typewriter.
|
||||
You would type a command to the computer, and it would type out any errors.
|
||||
It would not waste paper, ink, and time by typing out `COMMAND RUN SUCCESSFULLY` after each command.
|
||||
A silent machine meant a happy machine.
|
||||
|
||||
# Basic Usage
|
||||
|
||||
Open a file:
|
||||
|
||||
```sh
|
||||
ed file.md
|
||||
```
|
||||
|
||||
Insert a new line.
|
||||
|
||||
1. Press `i<Return>`
|
||||
1. Type the line.
|
||||
1. Finish your edit with single dot.
|
||||
|
||||
|
||||
```ed
|
||||
i
|
||||
dear diary,
|
||||
.
|
||||
```
|
||||
|
||||
Print the current line:
|
||||
|
||||
```ed
|
||||
p
|
||||
```
|
||||
|
||||
Change the current line:
|
||||
|
||||
```ed
|
||||
c
|
||||
Dear diary,
|
||||
.
|
||||
```
|
||||
|
||||
Delete the current line:
|
||||
|
||||
|
||||
```ed
|
||||
d
|
||||
```
|
||||
|
||||
|
||||
|
||||
Write the 'buffer' to disk:
|
||||
|
||||
|
||||
```ed
|
||||
w
|
||||
```
|
||||
|
||||
Quit:
|
||||
|
||||
```ed
|
||||
q
|
||||
```
|
||||
|
||||
# Working with Lines
|
||||
|
||||
Open that file:
|
||||
|
||||
|
||||
```ed
|
||||
ed file.md
|
||||
```
|
||||
|
||||
Add a line:
|
||||
|
||||
```ed
|
||||
a
|
||||
Fortune of the day:
|
||||
.
|
||||
```
|
||||
|
||||
Run `fortune`, and place the results inside the current buffer:
|
||||
|
||||
```ed
|
||||
r!fortune
|
||||
?
|
||||
```
|
||||
|
||||
The `?` indicates an error. We can ask what the error was with the command
|
||||
`h`:
|
||||
|
||||
```ed
|
||||
r!fortune
|
||||
?
|
||||
h
|
||||
Unexpected command suffix
|
||||
|
||||
```
|
||||
|
||||
The command `r` has something after it which makes no sense. It should have a
|
||||
space after the `r`!
|
||||
|
||||
|
||||
```ed
|
||||
r !fortune
|
||||
42
|
||||
```
|
||||
|
||||
That last line means `ed` has 42 characters in its buffer.
|
||||
|
||||
Read the current line, and show the line number:
|
||||
|
||||
|
||||
```ed
|
||||
n
|
||||
2 How many weeks are there in a light year?
|
||||
```
|
||||
|
||||
This means we are on line 2.
|
||||
|
||||
Fill up the file with fortunes:
|
||||
|
||||
```ed
|
||||
r !for x in 1 2 3 ; do echo --- && fortune ; done
|
||||
```
|
||||
|
||||
Print out which line in the file we are currently on:
|
||||
|
||||
```ed
|
||||
=
|
||||
12
|
||||
```
|
||||
|
||||
There are twelve lines. Go back up to line 3:
|
||||
|
||||
```ed
|
||||
3
|
||||
---
|
||||
```
|
||||
|
||||
So line 3 just has our delimiter: `---`.
|
||||
|
||||
Whenever you hit enter, `ed` prints the current line then moves to the next
|
||||
line.
|
||||
|
||||
|
||||
```ed
|
||||
I would have promised those terrorists a trip to Disneyland if it would have
|
||||
|
||||
gotten the hostages released. I thank God they were satisfied with the
|
||||
|
||||
missiles and we didn't have to go to that extreme.
|
||||
```
|
||||
|
||||
Go back a few lines:
|
||||
|
||||
```ed
|
||||
-3
|
||||
```
|
||||
|
||||
Print out 'current line', using the dot:
|
||||
|
||||
|
||||
```ed
|
||||
.
|
||||
```
|
||||
|
||||
Print current line with the number of that line:
|
||||
|
||||
|
||||
```ed
|
||||
.n
|
||||
11 Possessions increase to fill the space available for their storage.
|
||||
```
|
||||
|
||||
Print and number the next three lines:
|
||||
|
||||
|
||||
```ed
|
||||
.,+3n
|
||||
9 You have no real enemies.
|
||||
10 ------
|
||||
11 Possessions increase to fill the space available for their storage.
|
||||
```
|
||||
|
||||
Skip ahead four lines:
|
||||
|
||||
```ed
|
||||
+4
|
||||
?
|
||||
h
|
||||
Invalid address
|
||||
```
|
||||
|
||||
This is an `invalid address` because there are no more lines, so `ed` cannot print them.
|
||||
|
||||
# All Commands
|
||||
Meta Commands
|
||||
-------------
|
||||
|
||||
|
||||
| Aim | Command |
|
||||
|:------------------------------------------------|:---------------:|
|
||||
| Explain an error (`?`) | `h` |
|
||||
| Show a prompt when `ed` can take a command. | `P` |
|
||||
| Change the default filename to `rec.txt`. | `f rec.txt` |
|
||||
| Save the file. | `w` |
|
||||
| Append a line after line 8. | `8a` |
|
||||
| Move three lines down. | `+3` |
|
||||
| Move four lines back. | `-4` |
|
||||
| Move to the last line. | `$` |
|
||||
|
||||
Create
|
||||
------
|
||||
|
||||
| Aim | Command |
|
||||
|:--------------------------------------------------------------------|:---------------:|
|
||||
| Insert a line before line 5. | `5i` |
|
||||
| Append a line after line 8. | `8a` |
|
||||
| Read all of `~/.profile` into the current position. | `r ~/.profile` |
|
||||
| Run `dir` and place the results into the current position. | `r !dir` |
|
||||
| Copy lines 10 to 15 to line 23. | `10,15t23` |
|
||||
|
||||
|
||||
Read
|
||||
------
|
||||
|
||||
| Aim | Command |
|
||||
|:--------------------------------------------------------|:--------------:|
|
||||
| Print current line. | `.` or `p` |
|
||||
| Read lines 1 to 10. | `1,10p` |
|
||||
| Print and number lines 2 to 7. | 2,7n |
|
||||
| Find the next line ending with `fi` | /fi$/n |
|
||||
| Show the number of the next line starting with `if`. | `/^if/=` |
|
||||
| Find the line which contains `HOME`. | `?HOME?` |
|
||||
| Print the next five lines literally (showing tabs). | `.,+5l` |
|
||||
| Print from here till the end of the file. | `.,$p` |
|
||||
| Show all lines with `HOME` and show their numbers. | `g/HOME/n` |
|
||||
|
||||
|
||||
Update
|
||||
------
|
||||
|
||||
| Aim | Command |
|
||||
|:------------------------------------------------|:------------------------:|
|
||||
| On line 30, substitute `less` with `less -R` | `30s/less/less -R/` |
|
||||
| Change each line starting `#` to `##` | `,s^# /## /g` |
|
||||
| Move lines 50 to 55 to line 20. | `50,55m20` |
|
||||
|
||||
Delete
|
||||
------
|
||||
|
||||
| Aim | Command |
|
||||
|:------------------------------------------------|:-----------:|
|
||||
| Delete line 4. | `4d` |
|
||||
| Delete from here to four lines down. | `.,+4d |
|
||||
| Delete all lines starting with `#`. | `g/^#/d` |
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "vim basics"
|
||||
tags: [ "vim", "basic" ]
|
||||
tags: [ "vim", "basic", "TUI" ]
|
||||
---
|
||||
|
||||
## Instant nano replacement
|
||||
@@ -20,6 +20,5 @@ Keybind to exit this mode is `Ctrl+q`
|
||||
- [Learning Vim](vim/vi.md)
|
||||
- [Navigation](vim/navigate.md)
|
||||
- [Completion](vim/completion.md)
|
||||
- [Search](vim/search.md)
|
||||
- [Window Splits](vim/windows.md)
|
||||
- [Use vim bindings in bash](vim/vim_in_bash.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "vim completion"
|
||||
tags: [ "vim", "completion" ]
|
||||
tags: [ "vim", "completion", "TUI" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
|
||||
|
||||
32
writing/vim/linewrap.md
Normal file
32
writing/vim/linewrap.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: "vim linewrap"
|
||||
tags: [ "vim", "format", "linewrap", "TUI" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
|
||||
Wrap lines in a file to 80 characters with `gqG`.
|
||||
|
||||
Take this markdown file:
|
||||
|
||||
|
||||
```markdown
|
||||
This is a looooooooooooooooooooooooong line, and reeeeeeeeeeeeeeding it can be a paaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiiiiiiiiiiiiin in the aaaaaaaaaaaaaaaaaaaaaaaarse.
|
||||
```
|
||||
|
||||
Reformat the line to the proper text width by pressing `gqw`.
|
||||
The output looks like this:
|
||||
|
||||
```markdown
|
||||
This is a looooooooooooooooooooooooong line, and reeeeeeeeeeeeeeding it can be
|
||||
a paaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiiiiiiiiiiiiin in the
|
||||
aaaaaaaaaaaaaaaaaaaaaaaarse.
|
||||
```
|
||||
|
||||
This works with chunks of text in visual mode.
|
||||
|
||||
Change what width the text should be:
|
||||
|
||||
```vim
|
||||
:set textwidth=100
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "vim navigation"
|
||||
tags: [ "vim", "navigation" ]
|
||||
tags: [ "vim", "navigation", "TUI" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "vim search"
|
||||
tags: [ "vim", "search" ]
|
||||
title: "find and replace"
|
||||
tags: [ "vim", "search", "replace", "find", "TUI" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
Search for the next and or previous occurrence of the word under your cursor with `*` and `#`.
|
||||
@@ -9,7 +9,11 @@ Search and replace the first 'one' found with 'two':
|
||||
|
||||
`:%s/one/two/`
|
||||
|
||||
Same, but replace 'one' globally:
|
||||
Run the last substitution globally:
|
||||
|
||||
`g&`
|
||||
|
||||
Same, but just replace 'one' globally:
|
||||
|
||||
`:%s/one/two/g`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "How to Learn `vim`"
|
||||
tags: [ "vim", "learning" ]
|
||||
tags: [ "vim", "learning", "TUI" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "vim in bash"
|
||||
tags: [ "vim", "bash", "inputrc" ]
|
||||
tags: [ "vim", "bash", "inputrc", "TUI" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "vim windows"
|
||||
tags: [ "vim" ]
|
||||
tags: [ "vim", "TUI" ]
|
||||
requires: [ "vim basics" ]
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Vim Tricks"
|
||||
tags: [ "vim" ]
|
||||
tags: [ "vim", "TUI" ]
|
||||
requiered: [ "ssh" ]
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user