Epicyon : Python ActivityPub Application : configure to work on a Hestia domain?

I found a Python-based ActivityPub server, Epicyon (Epicyon ActivityPub server), that is easy to setup on a fresh server. However configuring it to run on an existing domain managed by HestiaCP will require some in-depth fiddling and troubleshooting.

I want to modify the Epicyon install instructions to make a scripted package that will work with HestiaCP. Upon success I would like to maintain a public repo so that others can just do a git clone and run a script, so they will not need to repeat all the rigamarole and troubleshooting.

My limited knowledge of HestiaCP internals puts me at a disadvantage so I would like pointers and thoughts from those who are experienced with HestiaCP.

Here is my HestiaCP setup scenario and the one for which I am targeting a solution:

The panel is managing several domains including the DNS for domains.
The panel is installed with the default settings.
Using Hestia interface I have created a user and a domain for Epicyon.
The domain works and is accessible from the web.
The domain root is in the usual place: /home/$USER/web/$DOMAIN.

It looks like these steps, and the setup for them can be scripted, which I can probably figure out from the HestiaCP documentation.

I believe that the chief goal is to get nginx for that domain to proxy the web requests between the Epicyon Python app and the web root for that domain. Epicyon has instructions for setting up certbot, which I wish to avoid if possible, so that HestiaCP can automatically manage SSL as usual.

So I need to answer some questions before fiddling any further.

  1. Where do I look to create a permanent HestiaCP template to enable the web user to run python on the selected domain?
  2. Where do I look to create a permanent HestiaCP nginx configuration like the one shipped with Epicyon, to proxy the web requests to the Python application?

In short, I need to run a Python application that mirrors its inputs and outputs in the web root for the domain, and has requests proxied by nginx from the web root to the Python application. The values established by the Epicyon systemd service appear like this:

ExecStart=/usr/bin/python3 /opt/epicyon/epicyon.py --port 443 --proxy 7156 --domain YOUR_DOMAIN --registration open --log_login_failures

And the values in the Epicyon nginx config have this line:

proxy_pass http://localhost:7156;

I need to figure out how to adapt this to HestiaCP in the right file paths for its unique templating scheme and file locations, so nginx knows how to proxy and so Python execution is properly authorized.

Epicyon install is straightforward for a fresh Debian install but it will not work with a domain managed by Hestia because of the way nginx is managed. I am trying to figure out the Hestia templates for nginx. The Epicyon template proxies web requests the the python backend. I want to be able to apply this template to a domain so that all the traffic to that domain is transparently proxied back and forth to the Epicyon port. How might I adapt the epicyon template for the hestia backend? Here is a copy-paste of the epicyon template from https://epicyon.net/#install :

server {
listen 80;
listen [::]:80;
server_name YOUR_DOMAIN;
access_log /dev/null;
error_log /dev/null;
client_max_body_size 31m;
client_body_buffer_size 128k;

limit_conn conn_limit_per_ip 10;
limit_req zone=req_limit_per_ip burst=10 nodelay;

index index.html;
rewrite ^ https://$server_name$request_uri? permanent;
}

server {
listen 443 ssl http2;
server_name YOUR_DOMAIN;

gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css text/vcard text/vcard+xml application/json application/ld+json application/javascript text/xml application/xml application/rdf+xml application/xml+rss text/javascript;

ssl_stapling off;
ssl_stapling_verify off;
ssl on;
ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem;
#ssl_dhparam /etc/ssl/certs/YOUR_DOMAIN.dhparam;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

add_header Content-Security-Policy "default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;

access_log /dev/null;
error_log /dev/null;

index index.html;

location /newsmirror {
root /var/www/YOUR_DOMAIN;
try_files $uri =404;
}

keepalive_timeout 70;
sendfile on;

location / {
proxy_http_version 1.1;
client_max_body_size 31M;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forward-Proto http;
proxy_set_header X-Nginx-Proxy true;
proxy_temp_file_write_size 64k;
proxy_connect_timeout 10080s;
proxy_send_timeout 10080;
proxy_read_timeout 10080;
proxy_buffer_size 64k;
proxy_buffers 16 32k;
proxy_busy_buffers_size 64k;
proxy_redirect off;
proxy_request_buffering off;
proxy_buffering off;
proxy_pass http://localhost:7156;
tcp_nodelay on;
}
}