overhauls of most service docs
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 33s

This commit is contained in:
2025-07-22 18:29:07 -04:00
parent 3f3a03ee05
commit 5184c84d50
57 changed files with 1726 additions and 551 deletions

Binary file not shown.

View File

@@ -5,11 +5,16 @@
- [Schlage Door Lock](#schlage-door-lock)
- [Philips Hue Lights](#philips-hue-lights)
- [Shelly](#shelly)
- [Relative Humidity Calculator](#relative-humidity-calculator)
- [Barometer](#barometer)
- [Relative Humidity Calculator](#relative-humidity-calculator)
- [Font Colors](#font-colors)
- [Light Indicator for Voice Assistant](#light-indicator-for-voice-assistant)
- [Blank Button (Spacer)](#blank-button-spacer)
- [Roku Remote](#roku-remote)
- [Flair Vent Battery](#flair-vent-battery)
- [Voice](#voice)
- [Custom Sentences](#custom-sentences)
- [Notifications](#notifications)
## Setup and Configuration
@@ -48,7 +53,51 @@ is quicker to pick up and transmit device information. Note that "gateway mode"
just enable bluetooth and rpc or select "active" from the configuration menu for the shelly
device.
### Relative Humidity Calculator
#### Barometer
<https://www.thoughtco.com/how-to-read-a-barometer-3444043>
A barometric reading over 30.20 inHg is generally considered high, and high pressure is associated with clear skies and calm weather.
If the reading is over 30.20 inHg (102268.9 Pa or 1022.689 mb):
- Rising or steady pressure means continued fair weather.
- Slowly falling pressure means fair weather.
- Rapidly falling pressure means cloudy and warmer conditions.
A barometric reading in the range of 29.80 and 30.20 inHg can be considered normal, and normal pressure is associated with steady weather.
If the reading falls between 29.80 and 30.20 inHg (100914.4102268.9 Pa or 1022.6891009.144 mb):
- Rising or steady pressure means present conditions will continue.
- Slowly falling pressure means little change in the weather.
- Rapidly falling pressure means that rain is likely, or snow if it is cold enough.
A barometric reading below 29.80 inHg is generally considered low, and low pressure is associated with warm air and rainstorms.
If the reading is under 29.80 inHg (100914.4 Pa or 1009.144 mb):
- Rising or steady pressure indicates clearing and cooler weather.
- Slowly falling pressure indicates rain.
- Rapidly falling pressure indicates a storm is coming.
A basic automation would look like
```yaml
It's {{ int(states("sensor.grouse_temp")) }} degrees and {{ states("weather.grouse_weather") }}. The relative humidity is {{ states("sensor.grouse_humidity") }}%. I'm seeing {{ int(states("sensor.grouse_wind_speed")) }}mph wind with gusts up to {{ int(states("sensor.grouse_wind_gust")) }}mph.
{% set pressure = float(states("sensor.grouse_rel_pressure")) %}
The barometer reads {{ pressure }}inHg.
{% if pressure > 30.20 %}
Fair weather is expected
{% elif pressure > 29.80 %}
Rain is possible
{% else %}
Rain is coming.
{% endif %}
```
#### Relative Humidity Calculator
<https://www.wikihow.com/Calculate-Humidity>
@@ -335,4 +384,32 @@ cards:
hold_action:
action: none
title: Left Living Room TV
```
```
### Flair Vent Battery
Flair vents report low battery at 2.4v. 3v is nominal/full.
```yaml
{% set volt_min=2.4 %}
{% set volt_max=3.0 %}
{% set volt_diff_max=0.6 %}
{{ (min(float(states("sensor.main_bedroom_29bf_voltage")) - volt_min, volt_diff_max) / volt_diff_max) * 100 }}
```
## Voice
### Custom Sentences
<https://developers.home-assistant.io/docs/voice/intent-recognition/template-sentence-syntax/#sentence-templates-syntax>
## Notifications
Notification Information:
<https://www.home-assistant.io/docs/automation/templating/>
```yaml
Triggered by {{ trigger.entity_id }}, Date: {{ now().strftime('%Y-%m-%d') }}, Time: {{ now().strftime('%H:%M') }}
```

View File

@@ -0,0 +1,21 @@
# Freedesktop Notes
Notes pertaining to the `.desktop` extension and desktop entries.
## Keys
<https://specifications.freedesktop.org/desktop-entry-spec/1.5/recognized-keys.html>
## Icons
<https://freedesktop.org/wiki/Specifications/icon-theme-spec/>
By default, apps should look in $HOME/.icons (for backwards compatibility), in $XDG_DATA_DIRS/icons and in /usr/share/pixmaps (in that order).
## Testing
Run a `.desktop` file from terminal with this:
```bash
gtk-launch gnome-system-monitor.desktop
```

View File

@@ -210,35 +210,7 @@ Now the status should be correct even after connecting/disconnecting when the co
## SSH
Generate a key with password protection:
```bash
# Omit "-N 'password'" to have it prompt you
ssh-keygen -f ~/.ssh/test-key -N 'PASSWORD'
```
Change the password for an ssh key:
```bash
# Use "-N ''" to remove the password
ssh-keygen -p -N 'PASSWORD' -f ~/.ssh/test-key
```
This is an example config entry in `~/.ssh/config`:
```conf
Host my-host
Hostname my-host.reeselink.com
User root
ProxyCommand none
ForwardAgent no
ForwardX11 no
Port 22
KeepAlive yes
IdentityFile ~/.ssh/id_my-host_rsa
```
You can ssh to that host with `ssh my-host` after adding a config entry.
See [README](/README.md#ssh-setup)
## Templates
@@ -652,7 +624,6 @@ Custom profiles are located at
Sync this with something like Nextcloud.
## Orca Slicer
<https://github.com/SoftFever/OrcaSlicer>

View File

@@ -14,55 +14,7 @@ and the operator will store information about each server.
## Setup SSH
On the operator:
```bash
export SSH_HOST=kube
ssh-keygen -t rsa -b 4096 -C ${USER}@${HOSTNAME} -f ~/.ssh/id_${SSH_HOST}_rsa
# Note: If you get "too many authentication failures" it's likely because you have too many private
# keys in your ~/.ssh directory. Use `-o PubkeyAuthentication` to fix it.
ssh-copy-id -o PubkeyAuthentication=no -i ~/.ssh/id_${SSH_HOST}_rsa.pub ducoterra@${SSH_HOST}.reeselink.com
ssh -i ~/.ssh/id_${SSH_HOST}_rsa -o 'PubkeyAuthentication=yes' ducoterra@${SSH_HOST}.reeselink.com
```
On the server:
```bash
# Copy authorized_keys to root
sudo cp ~/.ssh/authorized_keys /root/.ssh/authorized_keys
# Change your password
passwd
sudo su -
echo "PasswordAuthentication no" > /etc/ssh/sshd_config.d/01-prohibit-password.conf
echo '%sudo ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/01-nopasswd-sudo
systemctl restart ssh
```
On the operator:
```bash
cat <<EOF >> ~/.ssh/config
Host $SSH_HOST
Hostname ${SSH_HOST}.reeselink.com
User root
ProxyCommand none
ForwardAgent no
ForwardX11 no
Port 22
KeepAlive yes
IdentityFile ~/.ssh/id_${SSH_HOST}_rsa
EOF
# Test if you can SSH with a password
ssh -o PubkeyAuthentication=no ducoterra@${SSH_HOST}.reeselink.com
# Test that you can log into the server with ssh config
ssh $SSH_HOST
```
See [README](/README.md#ssh-setup)
## Fail2Ban

View File

@@ -285,4 +285,4 @@ output.eDP-2.enable \
output.eDP-2.mode.1920x1080@60 \
output.eDP-2.scale.1 \
output.eDP-2.position.0,0
```
```

View File

@@ -7,6 +7,7 @@
- [Fail2Ban](#fail2ban)
- [BTRFS Parent Volumes](#btrfs-parent-volumes)
- [BTRFS Snapshots](#btrfs-snapshots)
- [BTRFS Maintenance](#btrfs-maintenance)
- [TPM2 Luks Decryption](#tpm2-luks-decryption)
- [Change your password](#change-your-password)
- [Automatic Updates](#automatic-updates)
@@ -73,48 +74,7 @@ and the operator will store information about each server.
## Setup SSH
In this setup we'll allow ssh to the root user via key and keep the admin user for cockpit.
On the operator:
```bash
export SSH_HOST=kube
ssh-keygen -C ${USER}@${HOSTNAME} -f ~/.ssh/id_${SSH_HOST}_rsa
# Note: If you get "too many authentication failures" it's likely because you have too many private
# keys in your ~/.ssh directory. Use `-o PubkeyAuthentication` to fix it.
ssh-copy-id -o PubkeyAuthentication=no -i ~/.ssh/id_${SSH_HOST}_rsa.pub ducoterra@${SSH_HOST}.reeselink.com
ssh -i ~/.ssh/id_${SSH_HOST}_rsa ducoterra@${SSH_HOST}.reeselink.com
# Copy authorized_keys to root
sudo cp ~/.ssh/authorized_keys /root/.ssh/authorized_keys
exit
cat <<EOF >> ~/.ssh/config
Host ${SSH_HOST}
Hostname ${SSH_HOST}.reeselink.com
User root
Port 22
KeepAlive yes
IdentityFile ~/.ssh/id_${SSH_HOST}_rsa
EOF
ssh ${SSH_HOST}
# Disable password auth
echo "PasswordAuthentication no" > /etc/ssh/sshd_config.d/01-prohibit-password.conf
systemctl restart sshd
# OPTIONAL: Disable sudo password
echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/01-nopasswd-wheel
exit
# Test if you can SSH with a password
ssh -o PubkeyAuthentication=no ducoterra@${SSH_HOST}.reeselink.com
# Test that you can log into the server with ssh config
ssh $SSH_HOST
```
See [README](/README.md#ssh-setup)
## DNF
@@ -224,6 +184,13 @@ snapper -c root delete 1
Note - you probably don't want to keep yearly snapshots.
Edit `/etc/snapper/configs/root` and change `TIMELINE_LIMIT_YEARLY=` to `0`.
## BTRFS Maintenance
```bash
# Start a scrub in the foreground (-B) at /
btrfs scrub start -B /
```
## TPM2 Luks Decryption
Mostly taken from here:
@@ -324,7 +291,7 @@ TODO
## Common Storage Mounts
Note: mount these before you install the relavant package!
Note: mount these before you install the relevant package!
1. For virtual machines: `/var/lib/libvirt`
2. For podman: `/var/lib/containers`

View File

@@ -1,6 +1,7 @@
# Apps
- [Apps](#apps)
- [Common CLI Apps](#common-cli-apps)
- [Gear Lever](#gear-lever)
- [VSCode](#vscode)
- [DNF](#dnf)
@@ -47,6 +48,11 @@
- [KDiskMark](#kdiskmark)
- [Local Send](#local-send)
- [Evolution](#evolution)
- [Virtualization](#virtualization)
- [NVM](#nvm)
- [Ollama](#ollama)
- [UV](#uv)
- [Pipenv](#pipenv)
Flatpak installs are from Flathub unless otherwise noted.
@@ -58,6 +64,66 @@ flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.f
When prompted, prefer flathub.
## Common CLI Apps
Some common apps you'll probably want available.
```bash
sudo dnf install \
# Advanced text editor for code editing and other tasks.
vim \
# Network bandwidth measuring tool.
iperf3 \
# Command-line interface for managing Kubernetes clusters.
kubectl \
# Package manager and deployment tool for Kubernetes.
helm \
# Utility to monitor real-time network usage of processes.
nethogs \
# DevOps configuration management tool.
ansible \
# Terminal multiplexer.
tmux \
# Multimedia player with support for a wide range of codecs and file formats.
ffmpeg \
# Microsoft Windows compatibility layer.
wine \
# Archive utility similar to GNU tar, used to package files into single archive files.
unzip \
# A terminal activity monitor (top clone).
btop \
# Command-line JSON processor.
jq \
# YAML-based configuration-as-code tool for command-line interfaces written in Go, Rust, Python, and more.
yq \
# An image manipulation software suite based on ImageMagick.
ImageMagick \
# The Go programming language environment including a toolchain (gc) and libraries.
go \
# Rust package manager and compiler installation utility.
rust rustup \
# Distributed version control system, Git extension that adds support for large files like multimedia assets.
git git-lfs \
# Provides traditional network tools such as ifconfig, netstat, hostname, etc., in a single package.
net-tools \
# Document conversion tool and markup language converter.
pandoc \
# Comprehensive LaTeX distribution for high-quality typesetting of documents.
texlive-latex \
# Generate strong passwords.
pwgen \
# Reattach to running processes
reptyr \
# Netcat, for basic tcp/udp operations
netcat \
# 7zip support
p7zip \
# Make
make \
# GCC for compile
gcc
```
## Gear Lever
I would recommend you install Gear Lever to manage App Images:
@@ -296,6 +362,12 @@ At the very top of the config you can add a pin for a printer permanently with:
}
```
You'll need to open port 2021 udp
```bash
firewall-cmd --add-port=2021/udp --permanent
```
## Freecad
Benchy benchy benchy oh no, I can't do that, this is hard.
@@ -402,10 +474,11 @@ flatpak install io.github.thetumultuousunicornofdarkness.cpu-x
## Ungoogled Chromium
Chrom
<https://github.com/ungoogled-software/ungoogled-chromium?tab=readme-ov-file#automated-or-maintained-builds>
```bash
flatpak install io.github.ungoogled_software.ungoogled_chromium
sudo dnf copr enable wojnilowicz/ungoogled-chromium
sudo dnf install ungoogled-chromium
```
## Signal
@@ -507,4 +580,36 @@ You still use email? I still use email.
```bash
flatpak install org.gnome.Evolution
```
```
## Virtualization
```bash
# Virtualization
sudo dnf group install --with-optional virtualization
```
## NVM
<https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating>
## Ollama
<https://ollama.com/download>
Run the installation script as normal. Make sure you have the [ROCM](#rocm)
drivers installed for GPU acceleration. The script *should* automatically pull
the ROCM drivers after installing the base packages. If not, you should install
them manually.
For starting ollama as a service, follow the link below:
<https://github.com/ollama/ollama/blob/main/docs/linux.md#adding-ollama-as-a-startup-service-recommended>
## UV
<https://docs.astral.sh/uv/getting-started/installation/>
## Pipenv
<https://pipenv.pypa.io/en/latest/installation.html#installing-pipenv>

View File

@@ -4,37 +4,28 @@
- [Framework 16 Fixes](#framework-16-fixes)
- [Wake from Sleep](#wake-from-sleep)
- [Wrong keys pressed in the browser](#wrong-keys-pressed-in-the-browser)
- [Fix wifi disconnecting and reconnecting repeatedly on reboot/resume](#fix-wifi-disconnecting-and-reconnecting-repeatedly-on-rebootresume)
- [Wifi Powersave](#wifi-powersave)
- [Podman](#podman)
- [Autostarting services with quadlets](#autostarting-services-with-quadlets)
- [Toolbox](#toolbox)
- [Network](#network)
- [Firewall](#firewall)
- [VLAN Setup with nmcli](#vlan-setup-with-nmcli)
- [ZRAM](#zram)
- [Libraries](#libraries)
- [Common Libraries](#common-libraries)
- [Apps](#apps)
- [Common CLI Apps](#common-cli-apps)
- [Ungoogled Chromium](#ungoogled-chromium)
- [VSCode](#vscode)
- [Virtualization](#virtualization)
- [NVM](#nvm)
- [Ollama](#ollama)
- [UV](#uv)
- [Pipenv](#pipenv)
- [Backups](#backups)
- [BTRFS Snapshots](#btrfs-snapshots)
- [ROCM](#rocm)
- [Display](#display)
- [Scripted Display Modes](#scripted-display-modes)
- [Fixing generic Wayland icons on task alt tab](#fixing-generic-wayland-icons-on-task-alt-tab)
## Framework 16 Fixes
### Wake from Sleep
The keyboard/mouse can be pressed through the lid while in a backpack. Disable them to
prevent wake from sleep.
The keyboard/mouse can be pressed through the lid while in a backpack. Disable
them to prevent wake from sleep.
`/etc/udev/rules.d/69-suspend.rules`
@@ -55,61 +46,15 @@ sudo udevadm control --reload-rules && sudo udevadm trigger
### Wrong keys pressed in the browser
Sometimes keys will stop working when using search bars or do strange things like move the page around. This seems to be caused by some "alt" keypress combination. Pressing "alt" twice fixes it.
### Fix wifi disconnecting and reconnecting repeatedly on reboot/resume
Create a file in `/etc/systemd/system/reset-iwlwifi.service` with the following content:
```conf
[Unit]
Description=Reload iwlwifi on wake-up
After=suspend.target
After=multi-user.target
[Service]
ExecStartPre=rmmod iwlmvm iwlwifi
ExecStart=modprobe iwlwifi
[Install]
WantedBy=suspend.target
WantedBy=multi-user.target
```
```bash
systemctl daemon-reload
systemctl enable reset-iwlwifi.service
```
### Wifi Powersave
**NOTE: THIS DOESN'T WORK. IT CAUSES WIFI DISCONNECT AND RECONNECT ISSUES.**
<https://www.networkmanager.dev/docs/api/latest/settings-802-11-wireless.html>
<https://gist.github.com/jcberthon/ea8cfe278998968ba7c5a95344bc8b55>
<https://askubuntu.com/questions/1230525/ubuntu-20-04-network-performance-extremely-slow>
```bash
vim /etc/NetworkManager/conf.d/wifi-powersave-off.conf
```
```conf
[connection]
# Values are 0 (use default), 1 (ignore/don't touch), 2 (disable) or 3 (enable).
wifi.powersave = 2
```
```bash
systemctl restart NetworkManager
```
Sometimes keys will stop working when using search bars or do strange things
like move the page around. This seems to be caused by some "alt" keypress
combination. Pressing "alt" twice fixes it.
## Podman
Since you'll be using podman for most container-based services, you'll want to set the
the podman auth file to somewhere persistent, otherwise it'll get deleted every time you
reboot.
Since you'll be using podman for most container-based services, you'll want to
set the the podman auth file to somewhere persistent, otherwise it'll get
deleted every time you reboot.
Add this to your `.bashrc`:
@@ -122,8 +67,8 @@ Source that and then run `podman login` to create the file.
### Autostarting services with quadlets
If you want to run something as your user at boot (like a systemd process, think ollama) you can
create a user quadlets like so:
If you want to run something as your user at boot (like a systemd process,
think ollama) you can create a user quadlets like so:
```bash
# Generate the .container file
@@ -153,6 +98,65 @@ toolbox enter
## Network
### Firewall
Set the default firewall to `drop`
```bash
firewall-cmd --set-default-zone=drop
firewall-cmd --reload
```
Allow KDE Connect via 1714-1764 tcp/udp
```bash
firewall-cmd --add-port=1714-1764/udp --add-port=1714-1764/tcp --permanent
```
You can check if the firewall is working via `nmap` from another machine
Note, add `-r` to scan ports in order.
Note, add `-vv` to increase verbosity.
Note, add `-A` to perform OS detection, host lookup, etc.
Note, use `-F` to perform a quick scan against common ports.
```bash
export NMAP_HOST=10.2.0.49
# Scan for common ports on TCP
nmap -sT $NMAP_HOST
# Scan all ports on TCP
nmap -sT -p- $NMAP_HOST
# Scan specific port on TCP
nmap -sT -p5432 $NMAP_HOST
# Scan range of ports on TCP
nmap -sT -p1024-9999 $NMAP_HOST
# Scan for common ports on UDP
nmap -sU $NMAP_HOST
# Skip host up checking
nmap -Pn -sT $NMAP_HOST
# Scan all ports for everything (takes a really really long time)
nmap -Pn -sT -sU -p- $NMAP_HOST
# Scan using TCP ACK Ping (More serious check that attempts to bypass firewall, See nmap man page)
nmap -PA -p- $NMAP_HOST
```
Then, while running a scan:
v / V: Increase / decrease the verbosity level d / D: Increase / decrease the
debugging Level p / P: Turn on / off packet tracing ?: Print a runtime
interaction help screen
### VLAN Setup with nmcli
```bash
@@ -199,106 +203,6 @@ xz-devel \
libgle-devel
```
## Apps
### Common CLI Apps
```bash
sudo dnf install \
# Advanced text editor for code editing and other tasks.
vim \
# Network bandwidth measuring tool.
iperf3 \
# Command-line interface for managing Kubernetes clusters.
kubectl \
# Package manager and deployment tool for Kubernetes.
helm \
# Utility to monitor real-time network usage of processes.
nethogs \
# DevOps configuration management tool.
ansible \
# Terminal multiplexer.
tmux \
# Multimedia player with support for a wide range of codecs and file formats.
ffmpeg \
# Microsoft Windows compatibility layer.
wine \
# Archive utility similar to GNU tar, used to package files into single archive files.
unzip \
# A terminal activity monitor (top clone).
btop \
# Command-line JSON processor.
jq \
# YAML-based configuration-as-code tool for command-line interfaces written in Go, Rust, Python, and more.
yq \
# An image manipulation software suite based on ImageMagick.
ImageMagick \
# The Go programming language environment including a toolchain (gc) and libraries.
go \
# Rust package manager and compiler installation utility.
rust rustup \
# Distributed version control system, Git extension that adds support for large files like multimedia assets.
git git-lfs \
# Provides traditional network tools such as ifconfig, netstat, hostname, etc., in a single package.
net-tools \
# Document conversion tool and markup language converter.
pandoc \
# Comprehensive LaTeX distribution for high-quality typesetting of documents.
texlive-latex \
# Generate strong passwords.
pwgen \
# Reattach to running processes
reptyr \
# Netcat, for basic tcp/udp operations
netcat \
# 7zip support
p7zip
```
### Ungoogled Chromium
<https://github.com/ungoogled-software/ungoogled-chromium?tab=readme-ov-file#automated-or-maintained-builds>
```bash
sudo dnf copr enable wojnilowicz/ungoogled-chromium
sudo dnf install ungoogled-chromium
```
### VSCode
<https://code.visualstudio.com/docs/setup/linux#_rhel-fedora-and-centos-based-distributions>
### Virtualization
```bash
# Virtualization
sudo dnf group install --with-optional virtualization
```
### NVM
<https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating>
### Ollama
<https://ollama.com/download>
Run the installation script as normal. Make sure you have the [ROCM](#rocm) drivers installed
for GPU acceleration. The script *should* automatically pull the ROCM drivers after installing
the base packages. If not, you should install them manually.
For starting ollama as a service, follow the link below:
<https://github.com/ollama/ollama/blob/main/docs/linux.md#adding-ollama-as-a-startup-service-recommended>
### UV
<https://docs.astral.sh/uv/getting-started/installation/>
### Pipenv
<https://pipenv.pypa.io/en/latest/installation.html#installing-pipenv>
## Backups
### BTRFS Snapshots
@@ -307,7 +211,8 @@ For starting ollama as a service, follow the link below:
<http://snapper.io/manpages/snapper-configs.html>
We'll be using snapper, a tool for automating and controlling snapshot behavior.
We'll be using snapper, a tool for automating and controlling snapshot
behavior.
```bash
dnf install snapper dnf-plugin-snapper
@@ -335,8 +240,8 @@ snapper -c root create --description "test snapshot"
snapper -c root delete 1
```
Note - you probably don't want to keep yearly snapshots.
Edit `/etc/snapper/configs/root` and change `TIMELINE_LIMIT_YEARLY=` to `0`.
Note - you probably don't want to keep yearly snapshots. Edit
`/etc/snapper/configs/root` and change `TIMELINE_LIMIT_YEARLY=` to `0`.
## ROCM
@@ -400,4 +305,41 @@ output.eDP-2.position.0,0 \
output.eDP-2.primary \
output.eDP-2.mode.1920x1080@165 \
output.eDP-2.scale.1'
```
```
## Fixing generic Wayland icons on task alt tab
<https://epergo.com/posts/fix-generic-wayland-icon/>
1. Access Window Rules
Go to “System Settings > Window Management > Window Rules”.
2. Create a New Rule (If None Exist)
If the application does not have any rules already, create a new one:
1. Click on “Add New…”
2. Add a description (e.g., “Application settings for sublime_merge”)
3. Specify the “Window class (application)”
If youre unsure of the value for the window class, click “Detect Window
Properties”, then click on the application window. A pop-up with the
detected properties will be shown, and you can select the correct value.
3. Add Property
1. Click on “Add Property” and select “Desktop File Name”.
4. Find the Correct Desktop File Name
Standard Applications: If the application is installed using your distros
repositories, check the name in /usr/share/applications/. Flatpak
Applications: If its a Flatpak package, check the name in
/var/lib/flatpak/exports/share/applications/. For example, for Obsidian, it
will be md.obsidian.Obsidian (do not include the .desktop suffix).
5. Apply Settings
Apply the new settings and close the application if it was open. The next
time you open the application, it should show the correct icon.

View File

@@ -1,8 +0,0 @@
#!/bin/bash
kscreen-doctor \
output.eDP-2.enable \
output.eDP-2.position.0,0 \
output.eDP-2.primary \
output.eDP-2.mode.1920x1080@60 \
output.eDP-2.scale.1

View File

@@ -1,8 +0,0 @@
#!/bin/bash
kscreen-doctor \
output.eDP-2.enable \
output.eDP-2.position.0,0 \
output.eDP-2.primary \
output.eDP-2.mode.2560x1600@165 \
output.eDP-2.scale.1.25

View File

@@ -161,4 +161,4 @@ p = Path(\"%\"); \
realpath = (str(p.parent) + '/' if str(p.parent) != '.' else '') + p.stem + '.mp4'; \
subprocess.run(['mkdir', '-p', to_folder + str(Path(realpath).parent)]); \
subprocess.run(['ffmpeg', '-i', '%', '-c', 'copy', to_folder + realpath])"
```
```

View File

@@ -17,9 +17,9 @@
- [Cleaning up old snapshots](#cleaning-up-old-snapshots)
- [Creating and restoring snapshots](#creating-and-restoring-snapshots)
- [Filesystem ACLs](#filesystem-acls)
- [ISCSI Backup Volumes](#iscsi-backup-volumes)
- [Create Backup ZVOL](#create-backup-zvol)
- [Create Backup ISCSI Target](#create-backup-iscsi-target)
- [ISCSI](#iscsi)
- [Create ZVOL](#create-zvol)
- [Create ISCSI Target](#create-iscsi-target)
- [VMs](#vms)
- [Converting zvol to qcow2](#converting-zvol-to-qcow2)
- [Converting qcow2 to zvol](#converting-qcow2-to-zvol)
@@ -41,7 +41,7 @@
- [UPS Monitoring](#ups-monitoring)
- [ZFS Size Data](#zfs-size-data)
- [ZFS Rename](#zfs-rename)
- [ISCSI](#iscsi)
- [ISCSI](#iscsi-1)
- [ISCSI Base Name](#iscsi-base-name)
- [Archiving](#archiving)
- [Deleting snapshots](#deleting-snapshots)
@@ -247,9 +247,9 @@ Dataset -> Dataset details (edit) -> Advanced Options -> ACL Type (inherit)
setfacl -b -R /mnt/enc0/smb/media
```
## ISCSI Backup Volumes
## ISCSI
### Create Backup ZVOL
### Create ZVOL
1. Create a new dataset called "iscsi" and then a dataset under that called "backups"
1. Set sync to always
@@ -258,18 +258,22 @@ setfacl -b -R /mnt/enc0/smb/media
2. Create a new dataset under backups with the same name as your server hostname
3. Set the size to something reasonable (Note you may need to "force size")
### Create Backup ISCSI Target
### Create ISCSI Target
1. In System -> Services -> ISCSI set the Base Name following [these rules](#iscsi-base-name)
2. In Shared -> ISCSI -> Authorized Access -> Create a new authorized access
In Shared -> Block (iSCSI) Shares Targets
1. Global Target Configuration -> Base Name
1. set the Base Name following [these rules](#iscsi-base-name)
2. Authorized Access -> Add
1. Group ID arbitrary - just pick a number you haven't used
2. User: The connecting machine's ISCSI Base Name
3. Secret: A 16 character password with no special characters
3. Wizard -> Create New
1. Extent Name: `backup-<hostname>`
2. Extent Type: `Device`
3. Extent Device: The ZVOL you just created
4. Extent Sharing Platform: `Modern OS`
2. Discovery Authentication: Chap
3. User: The connecting machine's ISCSI Base Name
4. Secret: A 16 character password with no special characters
3. Extents -> Add
1. Name: `some-name`
2. Type: `Device`
3. Device: The ZVOL you just created
4. Sharing Platform: `Modern OS`
5. Protocol Options Portal: Either create new (0.0.0.0 and ::) or select your existing portal
6. Protocol Options Initiators: The base name of the connecting machine following [these rules](#iscsi-base-name)
4. Targets -> Select the backup-<hostname> target -> Edit

View File

@@ -16,55 +16,7 @@ and the operator will store information about each server.
## Setup SSH
On the operator:
```bash
export SSH_HOST=kube
ssh-keygen -t rsa -b 4096 -C ducoterra@${SSH_HOST}.reeselink.com -f ~/.ssh/id_${SSH_HOST}_rsa
# Note: If you get "too many authentication failures" it's likely because you have too many private
# keys in your ~/.ssh directory. Use `-o PubkeyAuthentication` to fix it.
ssh-copy-id -o PubkeyAuthentication=no -i ~/.ssh/id_${SSH_HOST}_rsa.pub ducoterra@${SSH_HOST}.reeselink.com
ssh -i ~/.ssh/id_${SSH_HOST}_rsa -o 'PubkeyAuthentication=yes' ducoterra@${SSH_HOST}.reeselink.com
```
On the server:
```bash
# Copy authorized_keys to root
sudo cp ~/.ssh/authorized_keys /root/.ssh/authorized_keys
# Change your password
passwd
sudo su -
echo "PasswordAuthentication no" > /etc/ssh/sshd_config.d/01-prohibit-password.conf
echo '%sudo ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/01-nopasswd-sudo
systemctl restart ssh
```
On the operator:
```bash
cat <<EOF >> ~/.ssh/config
Host $SSH_HOST
Hostname ${SSH_HOST}.reeselink.com
User root
ProxyCommand none
ForwardAgent no
ForwardX11 no
Port 22
KeepAlive yes
IdentityFile ~/.ssh/id_${SSH_HOST}_rsa
EOF
# Test if you can SSH with a password
ssh -o PubkeyAuthentication=no ducoterra@${SSH_HOST}.reeselink.com
# Test that you can log into the server with ssh config
ssh $SSH_HOST
```
See [README](/README.md#ssh-setup)
## Fail2Ban

View File

@@ -1,5 +0,0 @@
# Podman Server
## Notes
- create a btrfs subvolume for each user

View File

@@ -0,0 +1,68 @@
# Brick Tracker
<https://gitea.baerentsen.space/FrederikBaerentsen/BrickTracker/src/branch/master/docs/quickstart.md>
## Setup
1. Copy the `.env.sample` from <https://gitea.baerentsen.space/FrederikBaerentsen/BrickTracker/src/branch/master/.env.sample> to `.env`
2. Set the following:
1. `BK_AUTHENTICATION_PASSWORD`
2. `BK_AUTHENTICATION_KEY`
3. `BK_DATABASE_PATH`
4. `BK_INSTRUCTIONS_FOLDER`
5. `BK_MINIFIGURES_FOLDER`
6. `BK_PARTS_FOLDER`
7. `BK_REBRICKABLE_API_KEY`
8. `BK_SETS_FOLDER`
3. Create the docker compose yaml
```yaml
services:
bricktracker:
container_name: BrickTracker
restart: unless-stopped
image: gitea.baerentsen.space/frederikbaerentsen/bricktracker:1.2.2
ports:
- "3333:3333"
volumes:
- ./data:/var/lib/bricktracker
- ./static/instructions:/app/static/instructions
- ./static/minifigures:/app/static/minifigures
- ./static/parts:/app/static/parts
- ./static/sets:/app/static/sets
env_file: ".env"
```
4. Start the service: `docker compose up -d`
## Caddy
1. Create the new DNS record for your website
2. Create the Caddyfile at `./Caddyfile`
```conf
https://connors-legos.reeseapps.com:443 {
reverse_proxy 127.0.0.1:3333
}
```
3. Create the Caddy compose.yaml
```yaml
services:
caddy:
image: caddy:<version>
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
```

View File

@@ -0,0 +1,16 @@
services:
bricktracker:
container_name: BrickTracker
restart: unless-stopped
image: gitea.baerentsen.space/frederikbaerentsen/bricktracker:1.2.2
ports:
- "3333:3333"
volumes:
- /home/connorbricktracker/data:/var/lib/bricktracker
- /home/connorbricktracker/static/instructions:/app/static/instructions
- /home/connorbricktracker/static/minifigures:/app/static/minifigures
- /home/connorbricktracker/static/parts:/app/static/parts
- /home/connorbricktracker/static/sets:/app/static/sets
env_file: "/home/connorbricktracker/.env"
security_opt:
- label=disable

View File

@@ -0,0 +1,17 @@
[Container]
ContainerName=BrickTracker
EnvironmentFile=/home/connorbricktracker/.env
Image=gitea.baerentsen.space/frederikbaerentsen/bricktracker:1.2.2
PublishPort=3333:3333
SecurityLabelDisable=true
Volume=/home/connorbricktracker/data:/var/lib/bricktracker
Volume=/home/connorbricktracker/static/instructions:/app/static/instructions
Volume=/home/connorbricktracker/static/minifigures:/app/static/minifigures
Volume=/home/connorbricktracker/static/parts:/app/static/parts
Volume=/home/connorbricktracker/static/sets:/app/static/sets
[Service]
Restart=always
[Install]
WantedBy=default.target

View File

@@ -1,20 +1,10 @@
# Caddy Reverse Proxy
- [Caddy Reverse Proxy](#caddy-reverse-proxy)
- [DNS Records](#dns-records)
- [Install Caddy](#install-caddy)
- [Ansible](#ansible)
- [Manual](#manual)
## DNS Records
Before you can create a Caddyfile you need records that point to your server.
You can either create them manually in your DNS provider of choice or use the provided
ddns service:
1. Update the [ddns caddy records](/active/podman_ddns/secrets/caddy_records.yaml)
2. Run the [caddy ansible playbook](/active/podman_ddns/ddns.md#ansible-caddy-records)
- [Adding a new Caddy Record](#adding-a-new-caddy-record)
## Install Caddy
@@ -101,4 +91,15 @@ WantedBy=default.target
```bash
systemctl daemon-reload
systemctl restart caddy
```
```
## Adding a new Caddy Record
Before you can create a Caddyfile you need records that point to your server.
You can either create them manually in your DNS provider of choice or use the provided
ddns service:
1. Update the [ddns caddy records](/active/podman_ddns/secrets/caddy_records.yaml)
2. (Optional) Update the Caddyfile at `active/podman_caddy/secrets/Caddyfile`
3. Run the [caddy ansible playbook](/active/podman_ddns/ddns.md#ansible-caddy-records)

View File

@@ -1,26 +1,32 @@
# DDNS for Route53
- [DDNS for Route53](#ddns-for-route53)
- [Install](#install)
- [As a Systemd Service](#as-a-systemd-service)
- [Ansible Caddy Records](#ansible-caddy-records)
- [Ansible Git Record](#ansible-git-record)
- [Ansible Unifi External Records](#ansible-unifi-external-records)
- [Ansible Hostname reeselink records](#ansible-hostname-reeselink-records)
- [Quickly Update DDNS Records](#quickly-update-ddns-records)
- [Install a New DDNS Service](#install-a-new-ddns-service)
- [Ansible 3D Server Records](#ansible-3d-server-records)
- [Ansible Podman Record](#ansible-podman-record)
- [Ansible Unifi External Records](#ansible-unifi-external-records)
- [Ansible Hostname reeselink records](#ansible-hostname-reeselink-records)
- [Development](#development)
- [Testing](#testing)
- [Building Container Image](#building-container-image)
This service will automatically keep ipv4 and ipv6 records updated in AWS Route53.
This service will automatically keep ipv4 and ipv6 records updated in AWS
Route53.
**NOTE**: This requires the aws cli to be installed on each node with
credentials that can modify records in route53. See
[aws_iam](/active/aws_iam/aws_iam.md) and
[aws_cli](/active/aws_cli/aws_cli.md)
[aws_iam](/active/aws_iam/aws_iam.md) and [aws_cli](/active/aws_cli/aws_cli.md)
## Install
## Quickly Update DDNS Records
### As a Systemd Service
In the event of a record change you can quickly trigger the ddns services with
```bash
systemctl start --all ddns*.service
```
## Install a New DDNS Service
You need two files:
@@ -45,7 +51,12 @@ records:
hosted_zone_id: ABC123456789
```
Then you can install the ddns service with something like
Then you'll need to pick a server responsible for keeping those records
updated. Whichever host you run the service on will also be the host which
provides the public IP. Choose the host accordingly if it will be updating a
public IP on behalf of another server, as the IPv6 address will not be correct.
Now you can install the DDNS service with something like:
```bash
ansible-playbook \
@@ -60,27 +71,32 @@ active/podman_ddns/install_ddns.yaml \
See ansible playbook [install_ddns.yaml](/install_ddns.yaml)
#### Ansible Caddy Records
It's recommended that you have multiple secret `foobar-records.yaml` files for
multiple servers. If you have a podman server, it'll have its own
`podman-records.yaml`. If you have a docker server, it'll have its own
`docker-records.yaml`. Etc. etc.
### Ansible 3D Server Records
```bash
ansible-playbook \
-i ansible/inventory.yaml \
-l 3dserver \
active/podman_ddns/install_ddns.yaml \
-e "@active/podman_ddns/secrets/caddy_records.yaml"
-e "@active/podman_ddns/secrets/3dserver_records.yaml"
```
#### Ansible Git Record
### Ansible Podman Record
```bash
ansible-playbook \
-i ansible/inventory.yaml \
-l podman \
active/podman_ddns/install_ddns.yaml \
-e "@active/podman_ddns/secrets/git_record.yaml"
-e "@active/podman_ddns/secrets/podman_records.yaml"
```
#### Ansible Unifi External Records
### Ansible Unifi External Records
```bash
ansible-playbook \
@@ -90,7 +106,7 @@ active/podman_ddns/install_ddns.yaml \
-e "@active/podman_ddns/secrets/unifi_external_record.yaml"
```
#### Ansible Hostname reeselink records
### Ansible Hostname reeselink records
```bash
export PLAYBOOK_PATH=active/podman_ddns

View File

@@ -5,8 +5,6 @@ services:
image: docker.gitea.com/gitea:1.24
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=postgres:5432
- GITEA__database__NAME=gitea
@@ -16,15 +14,13 @@ services:
networks:
- gitea
volumes:
- /home/gitea/gitea_data:/data
- /home/gitea/gitea_data:/data:Z
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:2222"
depends_on:
- postgres
security_opt:
- label=disable
labels:
- "io.containers.autoupdate=registry"
@@ -39,9 +35,9 @@ services:
networks:
- gitea
volumes:
- /home/gitea/gitea_postgres:/var/lib/postgresql/data
security_opt:
- label=disable
- /home/gitea/gitea_postgres:/var/lib/postgresql/data:Z
labels:
- "io.containers.autoupdate=registry"
networks:
gitea:

View File

@@ -2,6 +2,7 @@
- [Gitea](#gitea)
- [Gitea on Rootless Podman](#gitea-on-rootless-podman)
- [A note on directories](#a-note-on-directories)
- [Create the gitea user](#create-the-gitea-user)
- [Convert Compose to Quadlet](#convert-compose-to-quadlet)
- [Install Quadlets](#install-quadlets)
@@ -15,6 +16,18 @@
## Gitea on Rootless Podman
### A note on directories
```bash
RunMode: prod
AppPath: /usr/local/bin/gitea
WorkPath: /data/gitea
CustomPath: /data/gitea
ConfigFile: /data/gitea/conf/app.ini
Data: /data/gitea/data/
```
### Create the gitea user
```bash

View File

@@ -4,13 +4,11 @@ Requires=postgres.service
[Container]
AutoUpdate=registry
ContainerName=gitea
Environment=USER_UID=1000 USER_GID=1000 GITEA__database__DB_TYPE=postgres GITEA__database__HOST=postgres:5432 GITEA__database__NAME=gitea GITEA__database__USER=gitea GITEA__database__PASSWD=gitea
Image=docker.gitea.com/gitea:1.24
Network=gitea.network
PublishPort=3000:3000
PublishPort=2222:2222
SecurityLabelDisable=true
Volume=/home/gitea/gitea_data:/data
Volume=/home/gitea/gitea_data:/data:Z
Volume=/etc/localtime:/etc/localtime:ro
[Service]

View File

@@ -1,10 +1,10 @@
[Container]
AutoUpdate=registry
ContainerName=postgres
Environment=POSTGRES_USER=gitea POSTGRES_PASSWORD=gitea POSTGRES_DB=gitea
Image=docker.io/library/postgres:15
Network=gitea.network
SecurityLabelDisable=true
Volume=/home/gitea/gitea_postgres:/var/lib/postgresql/data
Volume=/home/gitea/gitea_postgres:/var/lib/postgresql/data:Z
[Service]
Restart=always

View File

@@ -0,0 +1,31 @@
services:
testcraft:
image: gitea.reeseapps.com/services/minecraft:c1ca80b09b4645888e550efb0a2700b2ec1f1645
stdin_open: true
tty: true
volumes:
- /home/minecraft/testcraft:/mc_data
ports:
- 25565:25565
environment:
- MAX_RAM=4
- MIN_RAM=1
security_opt:
- "label=disable"
userns_mode: keep-id
restart: always
nimcraft:
image: gitea.reeseapps.com/services/minecraft:c1ca80b09b4645888e550efb0a2700b2ec1f1645
stdin_open: true
tty: true
volumes:
- /home/minecraft/nimcraft:/mc_data
ports:
- 25566:25565
environment:
- MAX_RAM=4
- MIN_RAM=1
security_opt:
- "label=disable"
userns_mode: keep-id
restart: always

View File

@@ -0,0 +1,108 @@
# Podman Template
- [Podman Template](#podman-template)
- [Install minecraft](#install-minecraft)
- [Create the minecraft user](#create-the-minecraft-user)
- [Convert Compose to Quadlet](#convert-compose-to-quadlet)
- [Install Quadlets](#install-quadlets)
- [Upgrade Quadlets](#upgrade-quadlets)
- [Expose minecraft](#expose-minecraft)
- [Backup minecraft](#backup-minecraft)
## Install minecraft
Find and replace minecraft with the name of the service.
### Create the minecraft user
```bash
useradd minecraft
su - minecraft
ssh-keygen
exit
cp ~/.ssh/authorized_keys /home/minecraft/.ssh/authorized_keys
chown minecraft:minecraft /home/minecraft/.ssh/authorized_keys
loginctl enable-linger $(id -u minecraft)
```
SSH into the server as minecraft
```bash
systemctl --user enable podman-restart
systemctl --user enable --now podman.socket
mkdir -p ~/.config/containers/systemd
```
### Convert Compose to Quadlet
Create a folder called `quadlets` in your podman_minecraft project.
```bash
# Generate the systemd service
podman run \
--security-opt label=disable \
--rm \
-v $(pwd)/active/podman_minecraft:/compose \
-v $(pwd)/active/podman_minecraft/quadlets:/quadlets \
quay.io/k9withabone/podlet \
-f /quadlets \
-i \
--overwrite \
compose /compose/compose.yaml
# Copy the files to the server
scp -r active/podman_minecraft/quadlets/. minecraft:~/.config/containers/systemd/
```
### Install Quadlets
```bash
ssh minecraft
export GAME_SERVER_NAME=testcraft
mkdir $GAME_SERVER_NAME
# Download the server jar (only needed once)
podman run \
-it \
--rm \
-e SERVER_VERSION=1.21.8 \
-v $(pwd)/$GAME_SERVER_NAME:/downloads \
--security-opt label=disable \
--userns keep-id \
docker.io/ducoterra/get-minecraft:latest
systemctl --user daemon-reload
systemctl --user restart $GAME_SERVER_NAME
```
### Upgrade Quadlets
```bash
scp -r quadlets/. minecraft:~/.config/containers/systemd/
ssh minecraft systemctl --user daemon-reload
ssh minecraft systemctl --user restart minecraft
```
## Expose minecraft
1. Create your minecraft ddns record first [following these docs](/active/podman_ddns/ddns.md#)
2. Create a SRV record in your DNS provider like the following:
| Field | Value |
| ----------- | -------------------------------------- |
| Record name | _minecraft._tcp.testcraft.reeseapps.com |
| Value | 0 5 25566 minecraft.reeseapps.com |
3. Test your record with `nslookup`
```bash
nslookup -q=srv _minecraft._tcp.testcraft.reeseapps.com
```
4. Access your server at your domain "testcraft.reeseapps.com"
## Backup minecraft
Follow the Borg [Create a Backup Service Docs](/active/systemd_borg/borg.md#create-a-backup-service)

View File

@@ -0,0 +1,14 @@
[Container]
Environment=MAX_RAM=4 MIN_RAM=1
Image=gitea.reeseapps.com/services/minecraft:c1ca80b09b4645888e550efb0a2700b2ec1f1645
PodmanArgs=--interactive --tty
PublishPort=25566:25565
SecurityLabelDisable=true
UserNS=keep-id
Volume=/home/minecraft/nimcraft:/mc_data
[Service]
Restart=always
[Install]
WantedBy=default.target

View File

@@ -0,0 +1,14 @@
[Container]
Environment=MAX_RAM=4 MIN_RAM=1
Image=gitea.reeseapps.com/services/minecraft:c1ca80b09b4645888e550efb0a2700b2ec1f1645
PodmanArgs=--interactive --tty
PublishPort=25565:25565
SecurityLabelDisable=true
UserNS=keep-id
Volume=/home/minecraft/testcraft:/mc_data
[Service]
Restart=always
[Install]
WantedBy=default.target

View File

@@ -0,0 +1,26 @@
[Unit]
Description=Nextcloud AIO Master Container
Documentation=https://github.com/nextcloud/all-in-one/blob/main/docker-rootless.md
After=local-fs.target
Requires=podman.socket
[Container]
ContainerName=nextcloud-aio-mastercontainer
Image=docker.io/nextcloud/all-in-one:latest
PublishPort=0.0.0.0:11001:8080
Volume=nextcloud_aio_mastercontainer:/mnt/docker-aio-config
Volume=/run/user/1001/podman/podman.sock:/var/run/docker.sock:Z
Network=bridge
SecurityLabelDisable=true
Environment=APACHE_PORT=11000
Environment=APACHE_IP_BINDING=0.0.0.0
Environment=WATCHTOWER_DOCKER_SOCKET_PATH=/run/user/1001/podman/podman.sock
Environment=NEXTCLOUD_DATADIR="/home/nextcloud/nextcloud_data"
Environment=SKIP_DOMAIN_VALIDATION=true
[Service]
Restart=always
[Install]
WantedBy=multi-user.target default.target

View File

@@ -55,7 +55,9 @@ systemctl --user enable --now podman.socket
### Create the container autostart service
As the nextcloud user.
Edit the autostart service to include "unless-stopped" containers.
As the nextcloud user:
`systemctl --user edit podman-restart.service`
@@ -63,7 +65,6 @@ As the nextcloud user.
[Service]
ExecStart=
ExecStart=/usr/bin/podman $LOGGING start --all --filter restart-policy=always --filter restart-policy=unless-stopped
ExecStop=
ExecStop=/bin/sh -c '/usr/bin/podman $LOGGING stop $(/usr/bin/podman container ls --filter restart-policy=always --filter restart-policy=unless-stopped -q)'
```
@@ -73,42 +74,21 @@ systemctl --user daemon-reload
### Install Nextcloud
`mkdir -p ~/.config/containers/systemd`
`vim ~/.config/containers/systemd/nextcloud-aio-mastercontainer.container`
```conf
[Unit]
Description=Nextcloud AIO Master Container
Documentation=https://github.com/nextcloud/all-in-one/blob/main/docker-rootless.md
After=local-fs.target
Requires=podman.socket
[Container]
ContainerName=nextcloud-aio-mastercontainer
Image=docker.io/nextcloud/all-in-one:latest
PublishPort=0.0.0.0:11001:8080
Volume=nextcloud_aio_mastercontainer:/mnt/docker-aio-config
Volume=/run/user/1001/podman/podman.sock:/var/run/docker.sock:Z
Network=bridge
SecurityLabelDisable=true
Environment=APACHE_PORT=11000
Environment=APACHE_IP_BINDING=0.0.0.0
Environment=WATCHTOWER_DOCKER_SOCKET_PATH=/run/user/1001/podman/podman.sock
Environment=NEXTCLOUD_DATADIR="/home/nextcloud/nextcloud_data"
Environment=SKIP_DOMAIN_VALIDATION=true
[Service]
Restart=always
[Install]
WantedBy=multi-user.target default.target
```
```bash
systemctl --user daemon-reload
systemctl --user start nextcloud-aio-mastercontainer
# Make the container systemd directory (if needed)
ssh nextcloud mkdir -p ~/.config/containers/systemd
# Create the nextcloud network with ipv6
ssh nextcloud podman network create --ipv6 nextcloud-aio
# Copy the quadlet files
scp \
active/podman_nextcloud/nextcloud-aio-mastercontainer.container \
nextcloud:.config/containers/systemd/
# Reload and restart the service
ssh nextcloud systemctl --user daemon-reload
ssh nextcloud systemctl --user restart nextcloud-aio-mastercontainer
```
### Install Caddy
@@ -167,7 +147,6 @@ systemctl daemon-reload
systemctl start caddy
```
### Firewall
Allow traffic to 11000 from your reverse proxy

View File

@@ -51,4 +51,4 @@ Compile and flash.
{+KC_ENT}{-KC_ENT}{1000}
// full screen
{+KC_LGUI}{+KC_PGUP}{-KC_PGUP}{-KC_LGUI}
```
```

View File

@@ -0,0 +1,12 @@
[Unit]
Description=Runs backup script for {{ repo_name }}
After=network.target
Wants=network-online.target
[Service]
Restart=no
Type=oneshot
ExecStart=/usr/local/script/backup-{{ repo_name }}.sh
[Install]
WantedBy=multi-user.target

View File

@@ -33,6 +33,7 @@ borg create \
--exclude-caches \
--exclude 'home/*/.cache/*' \
--exclude 'var/tmp/*' \
--exclude 'home/*/.snapshots/*' \
{% for dir in exclude_dirs %}
--exclude '{{ dir }}' \
{% endfor %}

View File

@@ -1,11 +1,11 @@
[Unit]
Description=Run Backup backup_{{ repo_name }}.service every hour
Description=Run Backup backup-{{ repo_name }}.service every day
[Timer]
OnCalendar=hourly
OnCalendar=*-*-* 2:00:00
AccuracySec=10min
Persistent=true
Unit=ddns.{{ item.record }}.service
Unit=backup-{{ repo_name }}.service
[Install]
WantedBy=timers.target

View File

@@ -1,13 +1,14 @@
# Borg Backup
- [Borg Backup](#borg-backup)
- [Server Setup](#server-setup)
- [Adding a Client](#adding-a-client)
- [Installing the Backup Service](#installing-the-backup-service)
- [Adding Nextcloud](#adding-nextcloud)
- [Manual Client Use](#manual-client-use)
- [Install Borg](#install-borg)
- [Set up a new root client](#set-up-a-new-root-client)
- [Create a Backup Service](#create-a-backup-service)
- [Check backup service logs](#check-backup-service-logs)
- [Run a Manual Backup](#run-a-manual-backup)
- [Back up and Entire System](#back-up-and-entire-system)
## Server Setup
## Install Borg
<https://borgbackup.readthedocs.io/en/stable/deployment/central-backup-server.html#user-and-group>
@@ -28,14 +29,16 @@ touch /home/backup/.ssh/authorized_keys
chown -R backup:backup /home/backup/.ssh
```
### Adding a Client
## Set up a new root client
Note: See [adding nextcloud](#adding-nextcloud) for nextcloud instructions here.
Backups will be run as the root user. Generate them an SSH key to
On the server as root:
```bash
export BACKUP_HOST=""
export BACKUP_HOST="borg.reeselink.com"
ssh-keygen -C ${USER}@${HOSTNAME} -f ~/.ssh/id_${BACKUP_HOST}
ssh-keygen -C root@${HOSTNAME} -f ~/.ssh/id_${BACKUP_HOST}
cat <<EOF >> ~/.ssh/config
Host ${BACKUP_HOST}
@@ -43,39 +46,20 @@ Host ${BACKUP_HOST}
IdentityFile ~/.ssh/id_${BACKUP_HOST}
User backup
Port 22
KeepAlive yes
EOF
```
Now on the server:
Now on borg.reeselink.com as root:
```bash
export CLIENT_FQDN=""
# Should look like ssh-rsa abcd1234 backup@fqdn.something.com
export SSH_PUBKEY=""
export AUTHKEY_ENTRY="command=\"cd /home/backup/repos/${CLIENT_FQDN}; borg serve --restrict-to-path /home/backup/repos/${CLIENT_FQDN}\",restrict ${SSH_PUBKEY}"
export CLIENT_FQDN="fqdn.reeseapps.com"
export SSH_PUBKEY="ssh-rsa abcd1234 backup@fqdn.something.com"
export BORG_COMMAND="cd /home/backup/repos/${CLIENT_FQDN}; borg serve --restrict-to-path /home/backup/repos/${CLIENT_FQDN}"
export AUTHKEY_ENTRY="command=\"${BORG_COMMAND}\",restrict ${SSH_PUBKEY}"
echo $AUTHKEY_ENTRY >> /home/backup/.ssh/authorized_keys
mkdir /home/backup/repos/${CLIENT_FQDN}
chown backup:backup /home/backup/repos/${CLIENT_FQDN}
```
Then back on the client:
```bash
ssh borg.reeselink.com
# root
borg init --encryption none backup@${BACKUP_HOST}:root
# home
borg init --encryption none backup@${BACKUP_HOST}:home
# app
borg init --encryption none backup@${BACKUP_HOST}:gitea
# another app
borg init --encryption none backup@${BACKUP_HOST}:nextcloud
```
### Installing the Backup Service
## Create a Backup Service
Create your vars file in `secrets/host_vars.yaml`
@@ -97,30 +81,29 @@ stop_user_services:
```
```bash
# Update all existing backup services for podman
for var_file in $(ls active/systemd_borg/secrets); do
ansible-playbook \
-i active/ansible/inventory.yaml \
-i ansible/inventory.yaml \
-l podman \
active/systemd_borg/install_backup.yaml \
-e "@active/systemd_borg/secrets/gitea_vars.yaml"
-e "@active/systemd_borg/secrets/$var_file"
done
```
#### Adding Nextcloud
## Check backup service logs
Rather than creating a client, just set the borg backup location to:
```text
backup@borg.reeselink.com:nextcloud
```bash
ssh podman journalctl -u 'backup-*' -f
```
Then run the backup. It will generate a pubkey. Copy this into the authorized_keys file.
## Manual Client Use
## Run a Manual Backup
```bash
borg list borg.reeselink.com:home
# Do not include the first / in the path
export PATH_TO_BACKUP=var/home/ducoterra
export PATH_TO_BACKUP=home/ducoterra
export BORG_REPO=borg.reeselink.com:home
# If not initialized, do that now
@@ -148,6 +131,10 @@ borg create \
-e "pp:/${PATH_TO_BACKUP}/.config/libvirt" \
-e "pp:/${PATH_TO_BACKUP}/.local/share/containers" \
-e "pp:/${PATH_TO_BACKUP}/.local/share/docker" \
-e "pp:/${PATH_TO_BACKUP}/.npm" \
-e "pp:/${PATH_TO_BACKUP}/.ollama" \
-e "pp:/${PATH_TO_BACKUP}/Downloads" \
-e "pp:/${PATH_TO_BACKUP}/Nextcloud" \
${BORG_REPO}::$(date +"%F-%H-%M-%S") \
/${PATH_TO_BACKUP}
@@ -156,4 +143,31 @@ borg mount $BORG_REPO::2025-05-14-00-44-05 /mnt/
# Restore a borg archive to a location (dry run)
borg extract --dry-run --list --strip-components 1 $BORG_REPO::my-files home/USERNAME
```
```
### Back up and Entire System
```bash
export BORG_REPO=borg.reeselink.com:root
borg create \
--verbose \
--filter AME \
--list \
--stats \
--progress \
--show-rc \
--compression lz4 \
--exclude root/.cache \
--exclude var/lib/docker \
--exclude var/lib/containers \
--exclude usr/share/ollama \
--exclude home \
--exclude proc \
--exclude dev \
--exclude sys \
--exclude tmp \
--exclude .snapshots \
${BORG_REPO}::$(date +"%F-%H-%M-%S") \
/
```

View File

@@ -8,36 +8,32 @@
path: /usr/local/script
state: directory
mode: '0755'
- name: Copy backup.service
- name: Copy backup-{{ repo_name }}.service
template:
src: backup.service
dest: /etc/systemd/system/backup-{{ repo_name }}.service
owner: root
group: root
mode: '0644'
- name: Copy backup.timer
- name: Copy backup-{{ repo_name }}.timer
template:
src: backup.timer
dest: /etc/systemd/system/backup-{{ repo_name }}.timer
owner: root
group: root
mode: '0644'
- name: Template backup.sh
- name: Template backup-{{ repo_name }}.sh
template:
src: backup.sh.j2
dest: /usr/local/script/backup-{{ repo_name }}.sh
owner: root
group: root
mode: '0744'
# - name: Reload ddns timer
# ansible.builtin.systemd_service:
# state: restarted
# name: ddns.{{ item.record }}.timer
# enabled: true
# daemon_reload: true
# loop: "{{ records }}"
# - name: Run ddns service
# ansible.builtin.systemd_service:
# state: restarted
# name: ddns.{{ item.record }}.service
# loop: "{{ records }}"
- name: Initialize Repo {{ borg_user }}@{{ borg_host }}:{{ repo_name }}
script: /usr/bin/borg init -e none {{ borg_user }}@{{ borg_host }}:{{ repo_name }}
ignore_errors: yes
- name: Reload backup timer backup-{{ repo_name }}.timer
ansible.builtin.systemd_service:
name: backup-{{ repo_name }}.timer
enabled: true
daemon_reload: true

View File

@@ -0,0 +1,8 @@
FROM alpine:latest
RUN apk add -U wireguard-tools
COPY wg0.conf /etc/wireguard/wg0.conf
CMD wg-quick up wg0 && \
wg set wg0 peer 'lvghTtIHSXzOfpruVHtRnnAiZJeUi8A6lzhE21GSJjA=' allowed-ips 10.10.0.2/32 && \
watch -n 1 wg

View File

@@ -0,0 +1,35 @@
# TODO
# 1. Ask for listen port
# 2. Ask for name of eth interface
apt-get update
apt-get upgrade -y
apt-get install -y raspberrypi-kernel-headers
apt install -y wireguard qrencode iptables
cat > /etc/sysctl.conf <<EOF
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF
reboot
cd /etc/wireguard
umask 077
export PRIVKEY=$(wg genkey)
echo $PRIVKEY | tee privatekey | wg pubkey | tee publickey
echo $PRIVKEY | tee --append /etc/wireguard/wg0.conf
cat > /etc/wireguard/wg0.conf <<EOF
[Interface]
Address = 10.10.0.1/24
Address = fd86:ea04:1111::1/64
SaveConfig = true
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = $PRIVKEY
EOF
sysctl -p
wg-quick up wg0
wg

View File

@@ -0,0 +1,28 @@
- name: Create Backup Service
hosts: all
vars_files:
- secrets/vars.yaml
tasks:
- name: Install the latest version of Wireguard Tools
ansible.builtin.dnf:
name: wireguard-tools
state: latest
- name: Create wg0.conf
template:
dest: /etc/wireguard/wg0.conf
src: wg0.conf.j2
owner: root
group: root
mode: '0600'
- name: enable and persist ip forwarding
sysctl:
name: net.ipv4.ip_forward
value: "1"
state: present
sysctl_set: yes
reload: yes
- name: start wireguard and enable on boot
systemd:
name: wg-quick@wg0
enabled: yes
state: started

View File

@@ -0,0 +1,47 @@
# TODO
# 1. Read server pubkey from file
wg
echo -n 'Client Name: '
read name
echo -n 'Last digit of client IP \(10.10.0.?\): '
read ip
echo -n 'Server PubKey: '
read server_pubkey
mkdir $name
cd $name
export PRIVKEY=$(wg genkey)
echo $PRIVKEY | tee $name"_privkey"
export PUBKEY=$(echo $PRIVKEY | wg pubkey)
echo $PUBKEY | tee $name"_pubkey"
cat > $name".conf" <<EOF
[Interface]
PrivateKey = $PRIVKEY
Address = 10.10.0.$ip/32, fd86:ea04:1111::$ip/128
DNS = 10.10.0.1
[Peer]
PublicKey = $server_pubkey
Endpoint = wireguard.reeseapps.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
EOF
cat >> /etc/wireguard/wg0.conf <<EOF
# $name
[Peer]
PublicKey = $PUBKEY
AllowedIPs = 10.10.0.$ip/32
EOF
wg set wg0 peer $PUBKEY allowed-ips 10.10.0.$ip/32
qrencode -t ansiutf8 < $name".conf"
cd ..
chmod -R 600 $name
wg

1
active/systemd_wireguard/qr.sh Executable file
View File

@@ -0,0 +1 @@
qrencode -t ansiutf8

View File

@@ -0,0 +1,5 @@
# {{ ansible_managed }}
[Interface]
Address = 10.0.1.1/24
ListenPort = 51820
PrivateKey = {{ server_privkey }}

View File

@@ -0,0 +1,39 @@
# Wireguard
## Install
```bash
ansible-playbook \
-i ansible/inventory.yaml \
-l wireguard \
active/systemd_wireguard/install_backup.yaml \
-e "@active/systemd_wireguard/secrets/vars.yaml"
```
## Add a client
```bash
export WG_IP_SUFFIX=$(cat IP && echo $(($(cat IP) + 1)) > IP)
export PRIVKEY=$(wg genkey)
export PUBKEY=$(echo $PRIVKEY | wg pubkey)
export SERVER_PUBKEY=$(cat publickey)
cat <<EOF > id_$WG_IP_SUFFIX
[Interface]
PrivateKey = $PRIVKEY
Address = 10.10.0.$WG_IP_SUFFIX/32
DNS = 10.10.0.1
[Peer]
PublicKey = $SERVER_PUBKEY
Endpoint = pihole.reeserelease.com:51820
AllowedIPs = 10.10.0.1/32
EOF
cat id_$WG_IP_SUFFIX | qrencode -t ansiutf8
echo "Added ID $WG_IP_SUFFIX"
echo "Press enter to continue"
read
wg set wg0 peer $PUBKEY allowed-ips 10.10.0.$WG_IP_SUFFIX/32
wg-quick down wg0 && wg-quick up wg0
```