pg_dump -U myUser -d my_database --schema-only > my_database_schema.sql
Cheatsheets
Export PostgreSQL Database Schema
📚 Language: bash
🛠 Framework:
📝 Topic: Database
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