Category Archives: Coding
I love to code interesting projects.
Run Programs Automatically on Linux
Server Daemons
The Greeks considered daemons to be spirits that work in the background, so that’s why daemons are called daemons.
The “d” in systemd stands for “daemon,” following the Unix convention of naming background processes by appending a lowercase “d” to their name. This reflects that systemd is a system daemon responsible for managing other daemons and system processes.
Systemctl is the primary command-line interface used to interact with and control the systemd system and service manager.
/etc/rc.local
is deprecated according to ChatGPT.
Graphical Applications
Using a desktop file in the autostart folder.
lxde?
If running a version with desktop GUI, put the desktop file for the program you want to auto-start in:
~/.config/autostart
Run Programs that Run Regularly
Crontab and systemd both schedule running programs. Crontab is simpler and much older. Systemd is the newer standard. It’s more complex but more powerful including logging etc.
To show all the services running:
systemctl list-units --type=service
To show the path and contents of a systemd unit file of a specific service:
systemctl cat awim-fastapi.service
To check the status of a service:
systemctl status awim-fastapi.service
To restart the service:
sudo systemctl restart awim-fastapi.service
React with Vite and Express API, using Node.js and TypeScript
Install the Latest Node.js
sudo apt install nodejs npm
sudo npm install n -g
For the latest stable version of Node JS:
sudo n stable
node --version
Create a New React App with Vite
Install Node.js, then in the directory where you want to install (often within project-name/client):
npm create vite@latest
npm run dev
Clone Existing React App
To clone a React project from Github, you clone it, then use the following command from the project subdirectory (to install it, which I don’t totally understand, but it works):
npm install --f
Move Entire App to a Subdirectory
You’ll want the React app to be contained in a subdirectory /client and the Express API contained in a subdirectory /api or /server. You can move the entire React app by moving all files into a subdirectory with the following commands:
mkdir client
git mv -k * client/
Create the Express API (mostly from ChatGPT)
mkdir api
cd api
npm init -y
Install express. Install mysql2 only if you are going to connect to a database:
npm install express cors dotenv mysql2
npm install --save-dev typescript ts-node nodemon @types/node @types/express @types/cors
UPDATE: ts-node is apparently a higher-performance version of tsx. I found ts-node to be a pain, so next time, use tsx instead.
npx tsc --init
Modify tsconfig.json for better compatibility:"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"moduleResolution": "node"
}
Add the following lines to package.json, scripts section to run typescript files directly with ts-node by compiling with tsc then running the dist/index.js file:
… ,
"type": "module",
"scripts": {
"dev": "ts-node src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
Make src/ directory:
mkdir src
cd src
Within src/, make index.ts and write the express API TS code, then run it with:
npm run dev
Running the Two Servers, API + React App
When they are separate, run the API from the api/ directory with:
npm run dev
and run the React app made with Vite from the client/ directory with:
npx vite
Deploy to a VPS
Fresh install an Ubuntu server and create non-root superuser per these instructions. Then:
sudo apt install -y nodejs npm nginx
sudo npm install -g serve pm2
Build and Run Frontend Manually
Going to frontend directory, then:
npm install
rm -rf dist (if necessary to clear previous build)
npm run build
package.json should be: "scripts": { "dev": "vite", "build": "tsc -b && vite build", ... }
serve -s dist --listen 4173
Run the Backend Manually
node index.js
CORS and .env Note
It is worth setting up – from the beginning – permissive CORS that utilizes .env. You can get pretty far ignoring CORS and .env in your initial local dev environment, but you do encounter CORS even in the local environment from the start. Facing and understanding the concepts of .env and CORS up front saves time overall.
Also using .env up front helps separate the environmental factors so you understand how things are working better.
Set up pm2
From the client/ directory:
pm2 start bash --name tv3clock-viteserve --cwd /home/nate/code/time-v3-astroclock4/client -- -c "npx serve -s dist --listen 6171"
From the api/ directory:
pm2 start index.js --name tv3clock-api
Set up pm2 for reboot:
pm2 save
pm2 startup
Then copy-paste the long command it gives you, per instructions.
Nginx as a Reverse Proxy
It is normal to run the sites with pm2 and use nginx to direct traffic to them.
Then add file
sudo nano /etc/nginx/sites-available/my-sites.conf
and edit with:
# -------------------------------
# Upstream definitions for PM2 apps
# -------------------------------
upstream tv3_frontend {
server 127.0.0.1:6171;
}
upstream tv3_api {
server 127.0.0.1:5001;
}
upstream tlom_frontend {
server 127.0.0.1:6172;
}
upstream tlom_api {
server 127.0.0.1:5002;
}
# -------------------------------
# timev3.com server block
# -------------------------------
server {
server_name timev3.com www.timev3.com;
# API proxy
location /api/ {
proxy_pass http://tv3_api/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# Frontend proxy
location / {
proxy_pass http://tv3_frontend/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen 80;
}
# -------------------------------
# mytlom.com server block
# -------------------------------
server {
server_name mytlom.com www.mytlom.com;
# API proxy
location /api/ {
proxy_pass http://tlom_api/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# Frontend proxy
location / {
proxy_pass http://tlom_frontend/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen 80;
}
Run a test on the new nginx configuration:
sudo nginx -t
Restart nginx:
sudo systemctl restart nginx
Windows Subsystem for Linux (WSL)
Develop in Python Using VS Code and WSL
PS > wsl --install
PS > wsl --list --online
PS > wsl --install -d Ubuntu-22.04
PS > wsl --list --verbose
PS > wsl --setdefault Ubuntu-22.04
PS > wsl
# code .
Windows PowerShell, Get Oriented
Windows PowerShell, Get Oriented
- The prompt is
PS C:\current\path> %VARIABLE_NAME%is a variable
Get the latest version of PowerShell
PS > winget search Microsoft.PowerShell
PS > winget install --id Microsoft.PowerShell --source winget
Scripting with PowerShell ISE
PS > Get-ExecutionPolicy -List
PS > Set-ExecutionPolicy -Scope Process RemoteSigned
Set Up Python from Scratch on Windows
Python is not natively-installed on Windows, unlike on Linux machines. This pretty much covers it: https://learn.microsoft.com/en-us/windows/python/web-frameworks
WordPress from Scratch
On a fresh Debian VPN. Per WordPress.org’s own list:
sudo apt install apache2
sudo apt install php
sudo apt install php-curl
sudo apt install php-[the rest of the recommended extensions]
php -m to see a list of the php extensions installed.
sudo apt install mariadb-server
sudo systemctl start apache2
sudo systemctl start mariadb
sudo mysql_secure_installation
mysql -u root -p
sudo apt install httpd mariadb mariadb-server php php-common php-mysql php-gd php-xml php-mbstring php-mcrypt php-xmlrpc unzip wget -y
Backup the Server
To make a backup file, sudo su root then navigate to root directory, and:
tar cvpzf backup.tgz --exclude=/proc --exclude=/lost+found --exclude=/backup.tgz --exclude=/mnt --exclude=/sys /
Download the resulting file.
To restore:
tar -xvpfz backup.tgz -C /
then, mkdir /proc, mkdir /lost+found, mkdir /mnt, mkdir /sys
reboot
Running a Server from a Raspberry Pi (Compared Alongside VPS)
A Server is a Physical Computer
There are various types of servers, but they all consist of a physical computer somewhere. This tutorial shows how to set up a server first with the simplest of physical devices you can have in your home for less than $20 and side-by-side with how to do it in its more abstract – and more common – form, a VPS (virtual private server) you can rent from a hosting service.
The two procedures are very analogous. Seeing them side-by-side helps make concrete what you are actually doing even though sometimes you can’t physically see it.
Server 1. Raspberry Pi Zero W Running Raspberry Pi OS (Debian, a flavor of Linux)
Can be purchased many places, such as Microcenter or Amazon.
Server 2. VPS (Virtual Private Server) Running Ubuntu 20.04 (a flavor of Linux)
I purchased a VPS from Hostwinds. There are various operating systems available. I used Ubuntu 20.04.
Connect to Your Server over a Network (or the Internet)
Connect Via Secure Shell (SSH)
I SSH login using the MobaXterm SSH Client. The server is usually a remote computer to which you do not have physical access, so instead of plugging in a keyboard, mouse and screen, you establish a connection that gives you access to the server’s command prompt. SSH stands for secure shell, meaning the data you transfer between your computer and the server are encrypted. SSH is enabled by default in Ubuntu, but not all Linux flavors.
Useful Linux Commands: https://vitux.com/40-most-used-ubuntu-commands/
1. Raspberry Pi Zero W
Connect the Raspberry Pi Zero to your LAN. There is a way to do this with command line but the Raspberry Pi OS connects to WiFi on the initial startup, so just do it on initialization. If you want, to view the saved password with the command line to know generally where WiFi passwords are stored, use
sudo grep psk= /etc/wpa_supplicant/*
which searches the appropriate directory for “psk=” and you see the stored WiFi keys.
Enable SSH. SSH is not enabled by default with Raspberry Pi Zero. Many tutorials tell you to add a blank file to the /boot folder called SSH (no extension at all). Use the command touch ssh, then reboot. If you do this, notice once SSH is enabled then the file gets deleted so you will not see any change other than the SSH login should work.
Or enable SSH by: in the raspberry pi terminal window, enter sudo raspi-config, select Interfacing Options, SSH, enable it.
2. Ubuntu
Must install openssh-server. Use sudo apt install openssh-server. Check status after install with sudo systemctl status ssh.
Find the Raspberry Pi’s own IP address in the command line with ip add or ip addr or ifconfig. The IP will show after wlan0: inet __.__.__.__ Within a LAN, it is often something like 192.168.1.* Alternatively, you can type your router’s IP into your browser and view a list of connected devices. Or, use nmap, sudo apt install nmap and the command sudo nmap -sn 192.168.1.0/24 (without sudo you won’t see all the MAC addresses)
2. VPS
On a VPS, SSH is (should be) enabled by your host to allow the purchaser to access it. You will get a default username and password from the hosting service who established the VPS with its default settings.
In MobaXterm, “Remote host” is where you specify the IP address of your server, available in your Hostwinds account.
The username is “root”
The password is whatever you set in Hostwinds
Optional: Update Operating System
1. Raspberry Pi OS
sudo apt update is the Debian update command (Raspberry Pi OS is based on Debian).
2. VPS
Update Ubuntu (only required if there is a new version of Ubuntu).*
*First, be sure you can login as the non-root super-user before updating Ubuntu as the new install will default to not allow root login. This means if you were planning to just use the existing root user with infinite powers you are now infinitely locked out of your own VPS and have to have your host re-initialize it. Your VPS host changed this setting when it set up your VPS so you can login but when you update the Ubuntu OS, the OS returns to the OS default which is to not allow SSH root login! This is a GREAT example of why to do the user basics as the very first step.
sudo do-release-upgrade
Update the advanced package tool:
(without the -get is newer, so I use it)sudo apt-get update
sudo apt update
Make Website Available Outside Your LAN
1. Raspberry Pi Zero W
Once the Pi server is serving a site on its IP within the LAN, making the site available outside the LAN (on the internet) is as simple as directing site requests that arrive to your internet IP to the Pi server. Sounds complicated, but when a browser looks for a website on the internet, it looks on port 80. Most routers have an option to direct all traffic arriving on a specific port to a specific IP within the LAN. Connect to your network’s router to configure it, usually by entering its IP (often 192.168.1.1) into a browser and logging in with a password you set. You should see an option like this under the advanced settings.
To Do: Establish an SSH Connection with SSH Keys for the Non-Root User
Normally, you generate a public and private key on your local computer then copy the public key to the server along with some settings. Hostwinds has an option in server management to generate the key, download the private key, and install the public key on the server. Reboot required.
MySQL / MariaDB
Mariadb forked from MySQL when Oracle bought MySQL, so I use MariaDB. The XAMPP controller that establishes localhost for developing uses MariaDB.
sudo apt install mariadb-server
sudo apt install libmariadb3 libmariadb-dev python3-dev
(I don’t think this was necessary) Enable mysqli in /etc/php/7.2/apache2/php.ini by removing comment ‘;’
extension=mysqli ; nate enabled this
also:
sudo phpenmod mysql
To login to MySQL from the Linux command prompt:
sudo mysql -u root or mysql -u username -p
From the MySQL command prompt, which is “MariaDB” – a version of MySQL, same thing, various self-explanatory commands:
MariaDB [(none)]> CREATE user 'new_username'@'localhost';
SELECT user, host, authentication_string FROM mysql.user;
DROP user 'new_username'@'localhost'
CREATE USER 'new_username'@'localhost' IDENTIFIED BY 'yourpassword';
or
CREATE USER 'new_username'@'%' IDENTIFIED BY 'yourpassword';
CREATE database yourdatabasename;
GRANT SELECT, INSERT, UPDATE ON yourdatabasename.* TO 'new_username'@'localhost';
or
GRANT ALL ON ...
SHOW GRANTS FOR new_username;
ALTER USER 'new_username'@'localhost' IDENTIFIED BY 'yournewpassword';
SHOW DATABASES;
USE yourdatabasename;
CREATE table
FLUSH PRIVILEGES not required if privileges were added with the GRANT command.
Connect to MariaDB Remotely
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
and change the bind-address line to:
bind-address = 0.0.0.0
Connect to MariaDB with Python
https://mariadb.com/resources/blog/how-to-connect-python-programs-to-mariadb
sudo apt install libmariadb3 libmariadb-dev
sudo apt install build-essential libssl-dev libffi-dev python3.13-dev
pip3 install mariadb
https://mariadb.com/resources/blog/how-to-connect-python-programs-to-mariadb
Apache
sudo apt install apache2 apache2-utils apache2-dev
Upload and Enable a Site
With the commands above, you gave the non-root super-user sufficient permission to set up sites.
Upload any site directory to /var/www/html/your_site/
Go to /etc/apache2/sites-available/ and copy the default .conf file:
cp 000-default.conf your_site.conf
and modify with the following information:
ServerName your_site.com
ServerAlias www.your_site.com
ServerAdmin you@email.com
DocumentRoot /var/www/html/your_site
Use the following command to enable the site. What it actually does is copy the .conf file from /sites-available/ to /sites-enabled/:
sudo a2ensite your_site opposite is sudo a2dissite your_site
sudo systemctl reload apache2
to show some server information:
ps aux | grep apache2 | less
#q
to get out of this command.
Astropy and Astroplan
Astropy
Installation instructions: https://docs.astropy.org/en/stable/install.html
Astropy required Python packages.
Astropy installation files archive with various ISA support. Download the appropriate wheel file, then install with the command pip3 install /home/pi/file_name.whl.
Astropy comes with the full Anaconda install. With Miniconda, the recommended way to install Astropy is using the command conda install astropy.
Astropy 0.3.0 is what Miniconda 3.5.5 installs. This is a much earlier version than I would have expected. Astropy 0.3 was released in Nov 2013.
Astropy 0.4 was released in Jul 2014. Therefore Astropy 0.3 was the latest version when Miniconda 3.5.5 was released and is probably why Miniconda 3.5.5 installs with Astropy 0.3.
Astropy v1.2 requires Python v2.7 or later and Numpy 1.7.0 or later.
Astropy v1.3: “vectors and coordinates can be reshaped like arrays.”
Astropy v2.0.0 started to implement Python 3 but specifically says does not change functionality with Python 2. However, from 2.0.0 to 2.0.18, Python 2 was gradually phased out.
Astropy v3.0 is the first version that supports only Python 3.
I think I want Astropy v1.3 – unless it won’t run for some reason. Why does Miniconda 3.5.5 install Astropy 0.3.0? Was it the current Astropy at the release time? Answer: yes, it was. Do the newer Astropy versions require newer ISA? At some point, I got a “need ARMv7” error so probably.
However, also unexpectedly, it updates Python from 2.7.7 to 2.7.8. Python 2.7.8 was released in Jul 2014.