2024-07-08
Daemonizing Applications With Pm2: A Step-By-Step Guide

PM2 daemonize any app

remember to set unbuffered output flag -u before running any python script, otherwise there will be no output in pm2 log


install and setup pm2 as daemon:

1
2
3
4
5
sudo apt install npm
sudo npm config set registry https://registry.npmmirror.com
sudo npm install -g pm2
pm2 startup

run program as daemon:

1
2
3
4
5
6
7
pm2 start -n <process_name> <executable_name> -- <process_arguments>
# save all processes
pm2 save
pm2 monit
pm2 logs
pm2 ls

Read More

2024-06-09
Secure Your Online Activity With Ufw: Blocking Incoming Connections On All Ports

UFW access control

when using long range public wifi it matters to block every port from incoming connections.

1
2
3
4
sudo ufw default deny
sudo ufw prepend reject in on <intetfece name>
sudo ufw restart

when configuration is done, remember to restart ufw and reconnect existing interfaces.

although remote clients are blocked, self-issued connections are not. so be sure to use another computer for testing ufw effectiveness before and after configuration.

Read More

2024-03-07
Nginx Use As Application Remapper

for more accurate results, use nginx-geoip2

to disable access by ip origin while exclude certain ranges, you can do this:

1
2
apt install -y libnginx-mod-http-geoip libgeoip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
http {
geoip_country /usr/share/GeoIP/GeoIP.dat;
geoip_proxy <internal_ip_ranges>;
geo $external_ip {
default 1;
<custom_exclusion_range> 0;
}
log_format geologfmt '$remote_addr - $remote_user <$geoip_country_code> [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log geologfmt;
}
server {
# boolean operator in nginx
# better do this with njs instead
set $a 0;
set $b 0;
if ($geoip_country_code != "<YOUR_COUNTRY_CODE>"){
set $a 1;
}
if ($external_ip){
set $a 1$a;
}
if ($a = 11){
set $b 1;
}
if ($b){return 444;}
}

remember to restart nginx service afterwards


enable http basic auth

1
2
sudo htpasswd -c /etc/nginx/passwd <username>

1
2
3
4
5
server {
auth_basic "<auth_window_title>";
auth_basic_user_file passwd;
}


Run nginx with debug info:

1
2
3
4
5
6
# within /etc/nginx/nginx.conf
http {
access_log /var/log/nginx/access.log debug;
error_log /var/log/nginx/error.log debug;
}


Remap a range of ports to suburl:

1
2
3
4
location ~ /server/(1[0-9][0-9][0-9][0-9]) {
proxy_pass http://localhost:$1/;
}


To handle CORS errors, one can write:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
location /api/ {
# add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Origin $http_origin;
add_header 'Access-Control-Allow-Headers' 'Content-Type';
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin *;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, x-requested-with';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
return 204;
}
proxy_pass http://localhost:7861/;
# proxy_set_header X-Forwarded-Prefix /api;
sub_filter "openapi.json" "api/openapi.json";
# sub_filter "SwaggerUIBundle({" "SwaggerUIBundle({ basePath: '/api', 'servers': [{url:'/api'}],";
sub_filter "static-offline-docs" "api/static-offline-docs";
sub_filter_once off;
}


After installing nginx, a default page is created under /var/www/html and config files are at /etc/nginx.

Run sudo systemctl restart nginx after config modification.


Edit the file at /etc/nginx/sites-available/default:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;
server_name localhost;
location /app1 {
proxy_pass http://localhost:8000;
}
location /app2 { # websocket support
proxy_pass http://localhost:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Origin ""; // to prevent unwanted 403
}
}


If you want to route FastAPI docs to nginx, you have to rewrite contents.

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
location /vllm/openapi.json {
proxy_pass http://localhost:8000/openapi.json;
sub_filter "\"paths\"" "\"servers\": [{\"url\": \"/vllm\"}], \"paths\"";
sub_filter_types application/json;
}
location /vllm/ {
proxy_pass http://localhost:8000/;
sub_filter "openapi.json" "vllm/openapi.json";
sub_filter_once off;
}
}

Read More