Ubuntu Server
Set up
Using Ubuntu 24.04 LTS which already has python3.12
1. install tree
sudo apt update
sudo apt upgrade -y
sudo apt-get install tree
sudo apt install python3.12-venv
2. Install Oh My Zsh
sudo apt install zsh -y
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
modify .zshrc
sudo nano ~/.zshrc- make changes:
# Nick added
alias python=python3.12
alias ss_status="sudo systemctl status"
alias ss_start="sudo systemctl start"
alias ss_stop="sudo systemctl stop"
echo ".zshrc loaded ✅"
3. Node.js
global for nick and all users
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt install -y nodejs
Claude Code
- consider
- I did this in the nws-kv23 server 2026-02-16, if this still works then continue using it.
1. make server level .npm
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=$HOME/.npm-global/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
2. Install claude
npm install -g @anthropic-ai/claude-code
4. Install GitHub
- from terminal:
ssh-keygen -t ed25519 -C "nrodrig1@gmail.com" - start ssh-agent:
eval "$(ssh-agent -s)" - create or modify ~/.ssh/config file
nano ~/.ssh/config
Host github.com
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519
- place your ssh key in the Github page: https://github.com/settings/keys
- copy SSH public key from terminal command:
cat ~/.ssh/id_ed25519.pub
5. Create folder structure
mkdir applications
mkdir databases
mkdir environments
mkdir project_resources
mkdir _config_files
mkdir logs
6. Setting Up limited_user for Application Deployment
A least-privilege user for running Python and Node.js applications via systemd services.
1. Create the User
sudo useradd --system --create-home --home-dir /home/limited_user --shell /usr/sbin/nologin limited_user
This creates a system user with a home directory at /home/limited_user, no login shell (cannot SSH or interactively log in), and no sudo group membership.
2. Give nick access to home/limited_user
This sets 770 permissions so the owner (limited_user) gets full access and the group gets read/execute.
sudo chmod 770 /home/limited_user
sudo chown limited_user:limited_user /home/limited_user
sudo usermod -aG limited_user nick
This sets the default ACL so any new files and directories created under /home/limited_user will grant the group read, write, and execute permissions.
sudo chmod g+s /home/limited_user
sudo apt install acl
sudo setfacl -d -m g::rwx /home/limited_user
If needed: recursive ownership
Give the limited_user ownership and make all contents owned by limited_user
sudo chown -R limited_user:limited_user /home/limited_user/
sudo chmod -R u=rwX,g=rwX /home/limited_user/
3. Set Up Application Directories
sudo -u limited_user mkdir /home/limited_user/applications
sudo -u limited_user mkdir /home/limited_user/databases
sudo -u limited_user mkdir /home/limited_user/environments
sudo -u limited_user mkdir /home/limited_user/project_resources
sudo -u limited_user mkdir /home/limited_user/_config_files
sudo -u limited_user mkdir /home/limited_user/logs
4. Install / build npm
sudo -u limited_user npm install
sudo -u limited_user npm run build
7. Clone TheServerManager
git clone git@github.com:costa-rica/TheServerManager.git
8. Set sudoer permissions
- create the nick-systemctl.csv file
- add the /home/nick/update-nick-systemctl.sh file
- run the update-nick-systemctl.sh file by typing to terminal:
/home/nick/update-nick-systemctl.sh - make file executable:
chmod +x /home/nick/update-nick-systemctl.sh
Common Ubuntu commands
# See content privileges
ls -l
# see user groups
groups [username]
service file commands
sudo systemctl daemon-reload
sudo systemctl enable personalweb03-api
sudo systemctl start personalweb03-api
sudo systemctl status personalweb03-api
# see logs
sudo journalctl -u personalweb03-api
sudo journalctl -u newsnexus10api.service -f
# Stop the timer (prevents future runs)
sudo systemctl stop personalweb03-services.timer
# Disable it (won't start on boot)
sudo systemctl disable personalweb03-services.timer
# Verify it's stopped
sudo systemctl list-timers
# reset failed (i.e. due to `StartLimitIntervalSec=1d`)
sudo systemctl reset-failed newsnexusrequesternewsapi01.service
Permissions
Example:
➜ NewsNexus10API git:(dev_02_logging) ls -ld /home/nick/logs
drwxr-xr-x 2 nick nick 4096 Dec 22 23:58 /home/nick/logs
Breakdown:
-
drwxr-xr-x 2 nick nick breaks down as follows:
- d → directory
- rwx (owner: nick) → read, write, enter directory
- r-x (group: nick) → read, enter directory, no write
- r-x (others) → read, enter directory, no write
-
2 = number of hard links (directory + parent reference).
-
Ownership:
- User: nick
- Group: nick
Set off .timer files
1.
sudo systemctl daemon-reload
sudo systemctl enable --now personalweb03-services.timer
check status
systemctl list-timers
Security
- see the /Users/nick/Documents/CheckLogsSuspiciousActivity project
- use codex to place syslog and auth.log files and just have it scan them.
Fail2ban
Install
sudo apt update
sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status
After editing jail files
sudo systemctl restart fail2ban
sudo fail2ban-client status
SSH Brute-Force Protection (sshd jail)
- Create file:
sudo nano /etc/fail2ban/jail.d/sshd.local
- Paste:
[sshd]
enabled = true
maxretry = 8
findtime = 30m
bantime = 2h
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 1w
- Apply and verify:
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
sudo fail2ban-client get sshd maxretry
sudo fail2ban-client get sshd findtime
sudo fail2ban-client get sshd bantime
Nginx 404 Burst Protection
- Create file:
sudo nano /etc/fail2ban/jail.local
- Paste:
[nginx-404]
enabled = true
filter = nginx-404
logpath = /var/log/nginx/access.log
backend = polling
maxretry = 20
findtime = 2m
bantime = 1h
- Apply and verify:
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status nginx-404
- Useful ops commands:
# See banned IPs for this jail
sudo fail2ban-client status nginx-404
# Unban one IP if needed
sudo fail2ban-client set nginx-404 unbanip <IP>
Nginx Rate Limiting
Edit the /etc/nginx/nginx.conf file. using sudo nano /etc/nginx/nginx.conf.
http {
##
# Nick added for rate limiting
##
# In http block
limit_req_zone $binary_remote_addr zone=general:10m rate=2r/s;
limit_req_zone $binary_remote_addr zone=strict:10m rate=1r/s;
# In server block - for most content
limit_req zone=general burst=20 nodelay;
##
# END Nick added for rate limiting
##
Restart nginx: sudo systemctl restart nginx
UFW
- allow from
sudo ufw allow from 69.207.163.8 to any port 22
VMWare Cloning VM
Step 1: copy vmdk and vmx files to new folder with new VM name
- original VM should be turned off
- copy vmdk and vmx files to new folder with new VM name
Step 2: ☝️ [After copy is finished] turn on old VM
- after finished copy turn ON the old VM
- This will help because when you get back to the Virtual Machines page / list you'll see two VMs with the same name
Step 3: register the cloned VM
- From datastore browser navigate to the new VM folder and right click on .vmx file and select "Register VM"
- From the Virtual Machines page / list rename new VM (which will be the one with the same name but turned off)
- Turn on the new VM
- rename the new VM from VMWare
- hostname from inside terminal of new machine
sudo hostnamectl set-hostname <new_hostname>
Using app_runner in nick group
1. create user
- create group:
getent group nick - add user to group with no login ability, no home dir:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin -G nick app_runner
2. set permissions
- Set dir to group rwx and recursivly:
sudo chown -R nick:nick /home/nick/project_resources
sudo chmod -R g+w /home/nick/project_resources
sudo find /home/nick/project_resources -type d -exec chmod g+s {} \;
Key Concepts
- deleting replacing database causes the permissions to be reset. To change permissions back to group rwx:
sudo chmod -R ug+rwX /home/nick/databases - Execute (x) on directories: Required to traverse (enter) a directory
- Read (r) on directories: Required to list directory contents
- Write (w) on directories: Required to create/delete files in the directory
- Capital X in chmod: Applies execute only to directories and files already executable
GoAccess
install
sudo apt update
sudo apt install goaccess
create report
- last 24 hours or whatever is in the log file
sudo goaccess /var/log/nginx/access.log \
--log-format=COMBINED \
--date-spec=hr \
--time-format=%H:%M:%S \
--date-format=%d/%b/%Y \
--output=/home/nick/access_maestro06_20251222.json
VMWare
Reverser Proxy Server:
- CPU: 1
- Memory: 2GB
- Hard Disk: 40GM
VM Options > Configuration Parameters to add:
- disk.EnableUUID: True