Cheatsheets

Export PostgreSQL Database Schema

📚 Language: bash

🛠 Framework:

📝 Topic: Database

pg_dump -U myUser -d my_database --schema-only > my_database_schema.sql


Autoupgrades

📚 Language: bash

🛠 Framework:

📝 Topic: Admin

##############################################################################################################################################################################
# Title: Auto-upgrades
# Description: This script will install unattended-upgrades package and configure it to automatically install security updates.
##############################################################################################################################################################################

# install unattended-upgrades

sudo apt-get install unattended-upgrades

# editing configuration file

sudo vim /etc/apt/apt.conf.d/50unattended-upgrades

# Enable the service for unattended upgrades by running the following command

sudo dpkg-reconfigure --priority=low unattended-upgrades

# To control how often updates are checked and installed, you can modify the file /etc/apt/apt.conf.d/20auto-upgrades:

sudo vim /etc/apt/apt.conf.d/20auto-upgrades

# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";

# To check the status of the unattended-upgrades service, run the following command:

sudo systemctl status unattended-upgrades

# To check the logs of the unattended-upgrades service, run the following command:

sudo less /var/log/unattended-upgrades/unattended-upgrades.log


Find files complex conditions

📚 Language: bash

🛠 Framework:

📝 Topic: Shell Scripting

#!/bin/bash

# This script finds and prints the content of all ASCII text files in the current directory
# that are exactly 1033 bytes in size, including handling file names with spaces.

# Step 1: Use `find` to search for all files in the current directory and subdirectories
# Step 2: Use `file` to determine the type of each file (text, binary, etc.)
# Step 3: Use `grep` to filter out only the files identified as "ASCII text"
# Step 4: Extract only the filenames using `cut` (everything before the colon `:` in the output of `file`)
# Step 5: For each filename, use `du` to get the file size in bytes
# Step 6: Use `awk` to filter for files that are exactly 1033 bytes
# Step 7: Use `cat` to print the contents of the matching files
# Each step is executed safely to handle files with spaces and special characters in their names.

# Loop through each file found by the command chain
find ./ -type f -exec file {} + | grep 'ASCII text' | cut -d: -f1 | while IFS= read -r file
do
  # Get the size of the file using `du` in bytes format (-b flag)
  du -b "$file" | 
  # Filter the output with `awk` to check if the file size is exactly 1033 bytes
  awk '$1 == 1033 {print $2}' | 
  # Use `xargs` to safely pass the filenames to `cat`, preserving spaces in filenames
  xargs -I{} cat "{}"
done

# Exit the script
exit 0


Search and replace in VIM

📚 Language: VIM

🛠 Framework:

📝 Topic: VIM

#!/bin/bash
# Quick Guide: Text Replacement in Vim
# This script contains examples of text replacement in Vim,
# along with detailed explanations as comments.

# ---------------------------------
# Replace in the Current Line
# ---------------------------------
# To replace all occurrences of a string in the current line, use:
:s/old/new/g
#
# Explanation:
# - `s`: Substitute command.
# - `old`: The text you want to replace.
# - `new`: The replacement text.
# - `g`: Global flag, ensuring all matches in the line are replaced.
#
# Example:
# Replacing all instances of 'board' with 'list' in the current line:
:s/board/list/g

# ---------------------------------
# Replace in the Entire File
# ---------------------------------
# To replace all occurrences of a string throughout the file, use:
:%s/old/new/g
#
# Explanation:
# - `%`: Applies the substitution to the entire file.
# - `s/old/new/`: The substitute command.
# - `g`: Global flag, ensuring all matches are replaced.
#
# Example:
# Replacing all instances of 'board' with 'list' in the entire file:
:%s/board/list/g

# ---------------------------------
# Using Regular Expressions (Regex)
# ---------------------------------
# Vim supports regex in text replacements. For example:
#
# To replace all words starting with "b":
 :%s/\bb\w*/newword/g
#
# Explanation:
# - `\b`: Matches a word boundary.
# - `b`: Matches the character "b".
# - `\w*`: Matches zero or more word characters after "b".
#
# This example replaces any word that starts with "b" with "newword".

# ---------------------------------
# Interactive Replacement
# ---------------------------------
# If you want to confirm each replacement, add the `c` flag:
:%s/old/new/gc
#
# Explanation:
# - `c`: Confirmation flag. Vim will ask for confirmation before
#   replacing each match.

# ---------------------------------
# Examples of Regex in Vim
# ---------------------------------
# Replace all instances of 'board' with 'list' only at the start of a line:
 :%s/^board/list/g
#
# Replace all instances of 'board' with 'list' only at the end of a line:
:%s/board$/list/g
#
# Replace all numbers with 'number':
:%s/\d+/number/g
# ---------------------------------
# Replace from Cursor to End of File
# ---------------------------------
# To replace all occurrences of a string from the current cursor position
# to the end of the file, use:
 :.,$s/old/new/g
#
# Explanation:
# - `.`: Refers to the current line where the cursor is located.
# - `$`: Refers to the last line of the file.
# - `s/old/new/`: The substitute command.
# - `g`: Global flag, ensuring all matches in the selected range are replaced.
#
# Example:
# Replace all instances of 'Modell' with 'Route' from the cursor position
# to the end of the file:
:.,$s/Modell/Route/g
#
# Interactive Confirmation:
# Add the `c` flag to confirm each replacement:
 :.,$s/Modell/Route/gc


OpenClaw VPS Setup

📚 Language: bash

🛠 Framework:

📝 Topic: Setup and Hardening

This cheatsheet walks through hardening a fresh Ubuntu 24.04 VPS from first root login to a fully isolated Docker-hosted OpenClaw gateway — accessible only over an SSH tunnel from your your System.

Before you start: You need a working SSH client on macOS, a YOUR_VPS_PROVIDER (or equivalent) VPS with Ubuntu 24.04, and an Anthropic API key. Generate a dedicated SSH key pair first:


ssh-keygen -t ed25519 -C "vps-YOUR_VPS_PROVIDER" -f ~/.ssh/id_ed25519_vps



Step 1: Initial Root Access & System Update


Connect as root and fully upgrade the system before touching anything else. Never configure a stale base.


ssh root@YOUR_VPS_IP

apt update && apt full-upgrade -y
apt autoremove -y
reboot



After reboot, reconnect and set your timezone:


ssh root@YOUR_VPS_IP

timedatectl set-timezone YOUR_TIMEZONE
timedatectl status



Step 2: Create an Admin User


Create a personal admin account with sudo. You will manage the server as this user — never as root, and never as the app user.


# On the VPS (as root)
adduser YOUR_USER
usermod -aG sudo YOUR_USER

# From your your System — copy your SSH public key to the new user
ssh-copy-id -i ~/.ssh/id_ed25519_vps.pub YOUR_USER@YOUR_VPS_IP



Open a new terminal tab and test the login before closing the root session:


ssh YOUR_USER@YOUR_VPS_IP
sudo whoami   # expected output: root



Step 3: Harden SSH


Disable root login, enforce key-only auth, and move SSH to a non-default port. Validate the config before restarting — a typo will lock you out.


# Back in the root session
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
nano /etc/ssh/sshd_config



Set or add these directives (adjust port if needed):


Port NEW_PORT
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
X11Forwarding no
AllowTcpForwarding no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2



Validate and restart SSH — open the firewall port first (Step 4) if you change the port:


sshd -t   # must produce no output
systemctl daemon-reload
systemctl restart ssh.socket
systemctl restart ssh

# From your your System — confirm login on the new port
ssh -p NEW_PORT YOUR_USER@YOUR_VPS_IP



Step 4: Configure UFW Firewall


Deny all incoming by default, then allow only SSH. Docker will be handled separately — it bypasses UFW's INPUT chain and requires its own mitigation.


sudo apt install ufw -y

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow NEW_PORT/tcp comment "SSH"

sudo ufw enable
sudo ufw status verbose



Block Docker from silently exposing container ports to the public internet by adding a DOCKER-USER chain rule:


sudo nano /etc/ufw/after.rules



Append this block at the very end of the file:


# DOCKER-USER — block unexpected container port exposure
*filter
:DOCKER-USER - [0:0]
-A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
-A DOCKER-USER -s 127.0.0.0/8 -j RETURN
-A DOCKER-USER -s 10.0.0.0/8 -j RETURN
-A DOCKER-USER -s 172.16.0.0/12 -j RETURN
-A DOCKER-USER -s 192.168.0.0/16 -j RETURN
-A DOCKER-USER -s 100.64.0.0/10 -j RETURN
-A DOCKER-USER -p tcp --dport 80 -j RETURN
-A DOCKER-USER -p tcp --dport 443 -j RETURN
-A DOCKER-USER -m conntrack --ctstate NEW -j DROP
-A DOCKER-USER -j RETURN
COMMIT



sudo ufw reload
# After Docker is installed, verify the chain exists:
sudo iptables -S DOCKER-USER



Step 5: Install Fail2Ban


Fail2Ban reads systemd journal logs and bans IPs that fail authentication. Configure it to watch the SSH jail on your custom port.


sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local



Find the [DEFAULT] section and the [sshd] section and set:


[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
backend  = systemd

[sshd]
enabled  = true
port     = NEW_PORT
logpath  = %(sshd_log)s
maxretry = 3
bantime  = 24h



sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status sshd



Step 6: System Monitoring (auditd, AIDE, logwatch)


Install auditd for syscall auditing, AIDE for file integrity checks, and logwatch for daily log digests.


# auditd
sudo apt install auditd audispd-plugins -y
sudo systemctl enable auditd
sudo systemctl start auditd

sudo nano /etc/audit/rules.d/hardening.rules



Paste these audit rules:


-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k sudoers
-w /etc/ssh/sshd_config -p wa -k sshd_config
-a always,exit -F arch=b64 -S execve -F euid=0 -k root_commands
-w /var/run/docker.sock -p rwxa -k docker_socket
-w /home/openclaw/.openclaw -p wa -k openclaw_state



sudo augenrules --load
sudo auditctl -l   # verify rules loaded



# AIDE — file integrity baseline
sudo apt install aide -y
sudo aideinit
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Schedule nightly check at 03:00
echo "0 3 * * * root /usr/bin/aide --check >> /var/log/aide.log 2>&1" | sudo tee /etc/cron.d/aide-check



# logwatch — daily digest
sudo apt install logwatch -y
sudo nano /etc/logwatch/conf/logwatch.conf
# Set: Output = mail | MailTo = your@email.com | Detail = Med

# Automatic security patches
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades



Step 7: Create the OpenClaw App User (no sudo)


The openclaw user owns the config and state directories. It has no sudo, no Docker group membership, and is never accessed via SSH directly — only by switching from the admin user.


sudo adduser openclaw --disabled-password --gecos ""

sudo mkdir -p /home/openclaw/.openclaw
sudo chown -R openclaw:openclaw /home/openclaw/.openclaw
sudo chmod 700 /home/openclaw/.openclaw



Step 8: Install Docker


Install from Docker's official repository. Do not add the openclaw user to the docker group — Docker group membership is equivalent to root access.


sudo apt remove docker docker-engine docker.io containerd runc 2>/dev/null

sudo apt install ca-certificates curl gnupg -y
sudo install -m 0755 -d /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

sudo docker run --rm hello-world



Step 9: Configure OpenClaw Secrets and Workspace


Switch to the openclaw user, create the directories that will be bind-mounted into the container, and write your API keys into a tightly-permissioned .env file.


sudo su - openclaw

mkdir -p ~/.openclaw/workspace
chmod 700 ~/.openclaw
chmod 700 ~/.openclaw/workspace

nano ~/.openclaw/.env



ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxx
# Generate with: openssl rand -hex 32
OPENCLAW_GATEWAY_TOKEN=your-64-char-random-token-here



chmod 600 ~/.openclaw/.env
exit   # back to admin user



# Clone the repo as admin, set ownership to openclaw
sudo -u openclaw git clone https://github.com/openclaw/openclaw.git /home/openclaw/openclaw-repo
sudo chown -R openclaw:openclaw /home/openclaw/openclaw-repo



Step 10: Build and Start OpenClaw in Docker


Run the setup script from the repo directory. It builds the image, runs the onboarding wizard, and starts the gateway container.


cd /home/openclaw/openclaw-repo

sudo OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest" \
     OPENCLAW_HOME_VOLUME="openclaw_home" \
     ./scripts/docker/setup.sh



If the script doesn't prompt correctly, run onboarding manually:


# Manual onboarding
sudo docker compose run --rm --no-deps --entrypoint node openclaw-gateway \
  dist/index.js onboard --mode local --no-install-daemon

# Set bind to loopback — never expose on LAN on a VPS
sudo docker compose run --rm --no-deps --entrypoint node openclaw-gateway \
  dist/index.js config set --batch-json \
  '[{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"loopback"},{"path":"gateway.auth.mode","value":"token"}]'

sudo docker compose up -d openclaw-gateway

# Verify
sudo docker compose ps
sudo docker compose logs -f openclaw-gateway



Step 11: Apply OpenClaw Security Hardening Config


Lock down the gateway config: loopback-only bind, token auth, mDNS off, filesystem restricted to workspace, exec tools set to deny-by-default.


sudo docker compose run --rm openclaw-cli security audit --deep

sudo -u openclaw nano /home/openclaw/.openclaw/openclaw.json



{
  "gateway": {
    "mode": "local",
    "bind": "loopback",
    "port": 18789,
    "auth": {
      "mode": "token",
      "token": "${OPENCLAW_GATEWAY_TOKEN}"
    }
  },
  "discovery": {
    "mdns": { "mode": "off" }
  },
  "session": {
    "dmScope": "per-channel-peer"
  },
  "tools": {
    "deny": ["gateway", "cron", "sessions_spawn", "sessions_send"],
    "fs": { "workspaceOnly": true },
    "exec": { "security": "deny", "ask": "always" }
  },
  "logging": {
    "redactSensitive": "tools"
  }
}



sudo chmod 600 /home/openclaw/.openclaw/openclaw.json
sudo docker compose restart openclaw-gateway



Step 12: Access the Dashboard via SSH Tunnel


The gateway listens only on 127.0.0.1:18789 inside the VPS. Forward that port to your your System over SSH — never expose it to the internet directly.


# On your your System — keep this terminal open while using the dashboard
ssh -p NEW_PORT -N -L 18789:127.0.0.1:18789 YOUR_USER@YOUR_VPS_IP



Then open http://127.0.0.1:18789/ in your browser and authenticate with the value of OPENCLAW_GATEWAY_TOKEN.

Add this to ~/.ssh/config on your your System for one-command access:


Host openclaw-vps
  HostName YOUR_VPS_IP
  User YOUR_USER
  Port NEW_PORT
  IdentityFile ~/.ssh/id_ed25519_vps
  LocalForward 18789 127.0.0.1:18789



ssh -N openclaw-vps



Step 13: Verify the Full Setup


Run health checks and confirm all security controls are in place before considering this server production-ready.


# Health endpoints
curl -fsS http://127.0.0.1:18789/healthz
curl -fsS http://127.0.0.1:18789/readyz

# Gateway and security audit
sudo docker compose run --rm openclaw-cli gateway status
sudo docker compose run --rm openclaw-cli security audit --deep

# Container isolation — must NOT be root, must NOT have Docker socket
sudo docker compose exec openclaw-gateway whoami          # expected: node
sudo docker compose exec openclaw-gateway ls /var/run/docker.sock 2>&1   # expected: No such file

# UFW and DOCKER-USER chain
sudo ufw status verbose
sudo iptables -S DOCKER-USER   # verify DROP rule is present

# Fail2Ban
sudo fail2ban-client status
sudo fail2ban-client status sshd



Ongoing Maintenance


Common day-to-day operations once the server is running.


# Update OpenClaw
cd /home/openclaw/openclaw-repo
sudo docker compose pull
sudo docker compose up -d

# View gateway logs
sudo docker compose logs -f openclaw-gateway

# Backup state
sudo tar -czf openclaw-backup-$(date +%Y%m%d).tar.gz \
  /home/openclaw/.openclaw/openclaw.json \
  /home/openclaw/.openclaw/credentials/ \
  /home/openclaw/.openclaw/agents/

# Rotate the gateway token
openssl rand -hex 32
sudo nano /home/openclaw/.openclaw/.env
sudo docker compose restart openclaw-gateway


Hardhat Setup

📚 Language: Solidity

🛠 Framework:

📝 Topic: Solidity Development

##############################################################################################################################################################################
# Title: Hardhat Setup & Deployment
# Description: This script helps you set up a Hardhat project with multiple contracts and deploy them via Ignition to a local network.
##############################################################################################################################################################################

# Node.js and npm must be installed.
# Install Hardhat locally

npm install --save-dev hardhat

# Initialize a new Hardhat project

npx hardhat init

# Example project structure:
# test-project/
# ├── contracts/
# │   ├── Contract1.sol
# │   ├── Contract2.sol
# │   ├── Contract3.sol
# │   ├── Contract4.sol
# │   └── Contract5.sol
# ├── ignition/
# │   └── modules/
# │       └── ContractModule.js
# ├── hardhat.config.js
# └── package.json

# Content of the file ignition/modules/ContractModule.js:
# (commented for inclusion in shell script)

# >>> BEGIN JS MODULE (DO NOT EXECUTE IN SHELL) <<<
# const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
#
# module.exports = buildModule("ContractModule", (m) => {
#   const contract1 = m.contract("Contract1");
#   const contract2 = m.contract("Contract2");
#   const contract3 = m.contract("Contract3");
#   const contract4 = m.contract("Contract4");
#   const contract5 = m.contract("Contract5");
#
#   return { contract1, contract2, contract3, contract4, contract5 };
# });
# >>> END JS MODULE <<<

# Start the local Hardhat network

npx hardhat node

# Deploy the contracts using Hardhat Ignition

npx hardhat ignition deploy ignition/modules/ContractModule.js --network localhost