[GH-ISSUE #4420] Bare metal / VM install instructions - not the entire world is docker #2829

Open
opened 2026-02-26 07:36:55 +03:00 by kerem · 8 comments
Owner

Originally created by @netchild on GitHub (Mar 7, 2025).
Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/4420

Is your feature request related to a problem? Please describe.

The world is not docker. There are use cases for it, but there are a lot of uses cases where docker is not the best solution. Just providing install instructions for docker leaves out those situations where something else than docker is required / needed / decided upon / forced, nginx runs on a lot of platforms, not only on docker. There may be unsupported architectures in use (risc-v, cheri, powerpc, ...), there may be unsupported OS in use (*BSDs), there may be a requirement that it runs in a VM (no matter if because of policy, security reasons, or whatever), and so on... where your project would run simply fine. It also prevents an OS specific package management to pickup your project as an easy package install. There may also be a security requirement that the software bill of materials is easily inspectable and that open source stuff has to be manually fixable independently from the original developer, that no pre-build image from an unknown source is allowed to be installed.

The dockerfile is not an install instruction. You are locking yourself into a niche instead of opening yourself to the entire open source ecosystem.

Describe the solution you'd like

Provide bare metal install instructions (list of requirements, initial config, where to install what from your repo).

Originally created by @netchild on GitHub (Mar 7, 2025). Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/4420 **Is your feature request related to a problem? Please describe.** The world is not docker. There are use cases for it, but there are a lot of uses cases where docker is not the best solution. Just providing install instructions for docker leaves out those situations where something else than docker is required / needed / decided upon / forced, nginx runs on a lot of platforms, not only on docker. There may be unsupported architectures in use (risc-v, cheri, powerpc, ...), there may be unsupported OS in use (*BSDs), there may be a requirement that it runs in a VM (no matter if because of policy, security reasons, or whatever), and so on... where your project would run simply fine. It also prevents an OS specific package management to pickup your project as an easy package install. There may also be a security requirement that the software bill of materials is easily inspectable and that open source stuff has to be manually fixable independently from the original developer, that no pre-build image from an unknown source is allowed to be installed. The dockerfile is not an install instruction. You are locking yourself into a niche instead of opening yourself to the entire open source ecosystem. **Describe the solution you'd like** Provide bare metal install instructions (list of requirements, initial config, where to install what from your repo).
Author
Owner

@B0F1B0 commented on GitHub (Mar 9, 2025):

Hi netchild,

if you have Proxmox, you can easy install NPM - Nginx Proxy Manager in an LXC Container with the [Proxmox VE Helpder-Scripts](https://community-scripts.github.io/ProxmoxVE/scripts?id=nginxproxymanager).

Default settings:
OS: Debian 12
CPU: 2vCPU
RAM: 1GB
HDD: 4GB

The Proxmox VE Helper script executes this script, among others.

I have adapted this script that the following script will do perform a "bare metal" installation (Version 2.12.3).
Since I am currently still on version 2.11.3 and would like to upgrade to 2.12.XXX, but version 2.12.3 (latest) is not working properly for me (streams not working), I also added version 2.12.0 till 2.12.2 as a comment in the script.

Search for Keyword: ######LATETEST RELEASE there you can comment out/in the necessary Version.


#!/usr/bin/env bash


echo "Installing Dependencies"
apt-get update
apt-get -y install \
  sudo \
  mc \
  curl \
  gnupg \
  make \
  gcc \
  g++ \
  ca-certificates \
  apache2-utils \
  logrotate \
  build-essential \
  git
echo "Installed Dependencies"

echo "Installing Python Dependencies"
apt-get install -y \
  python3 \
  python3-dev \
  python3-pip \
  python3-venv \
  python3-cffi \
  python3-certbot \
  python3-certbot-dns-cloudflare
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
pip3 install certbot-dns-multi
python3 -m venv /opt/certbot/
echo "Installed Python Dependencies"

VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"

echo "Installing Openresty"
wget -qO - https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg
echo -e "deb http://openresty.org/package/debian bullseye openresty" >/etc/apt/sources.list.d/openresty.list
apt-get update
apt-get -y install openresty
echo "Installed Openresty"

echo "Installing Node.js"
bash <(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh)
source ~/.bashrc
nvm install 16.20.2
ln -sf /root/.nvm/versions/node/v16.20.2/bin/node /usr/bin/node
echo "Installed Node.js"

echo "Installing pnpm"
npm install -g pnpm@8.15
echo "Installed pnpm"

######LATETEST RELEASE
RELEASE=$(curl -s https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
  grep "tag_name" |
  awk '{print substr($2, 3, length($2)-4) }')

wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz

#RELEASE=2.12.2
##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz
#RELEASE=2.12.1
##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz
#RELEASE=2.12.0
##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz


cd ./nginx-proxy-manager-${RELEASE}
echo "Downloaded Nginx Proxy Manager v${RELEASE}"

echo "Setting up Environment"
ln -sf /usr/bin/python3 /usr/bin/python
ln -sf /usr/bin/certbot /opt/certbot/bin/certbot
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
ln -sf /usr/local/openresty/nginx/ /etc/nginx

sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json
sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json

#sed -i 's|"fork-me": ".*"|"fork-me": "Proxmox VE Helper-Scripts"|' frontend/js/i18n/messages.json
#sed -i "s|https://github.com.*source=nginx-proxy-manager|https://helper-scripts.com|g" frontend/js/app/ui/footer/main.ejs
sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf")
for NGINX_CONF in $NGINX_CONFS; do
  sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
done

mkdir -p /var/www/html /etc/nginx/logs
cp -r docker/rootfs/var/www/html/* /var/www/html/
cp -r docker/rootfs/etc/nginx/* /etc/nginx/
cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager
ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
rm -f /etc/nginx/conf.d/dev.conf

mkdir -p /tmp/nginx/body \
  /run/nginx \
  /data/nginx \
  /data/custom_ssl \
  /data/logs \
  /data/access \
  /data/nginx/default_host \
  /data/nginx/default_www \
  /data/nginx/proxy_host \
  /data/nginx/redirection_host \
  /data/nginx/stream \
  /data/nginx/dead_host \
  /data/nginx/temp \
  /var/lib/nginx/cache/public \
  /var/lib/nginx/cache/private \
  /var/cache/nginx/proxy_temp

chmod -R 777 /var/cache/nginx
chown root /tmp/nginx

echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf

if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
  openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem &>/dev/null
fi

mkdir -p /app/global /app/frontend/images
cp -r backend/* /app
cp -r global/* /app/global
echo "Set up Enviroment"

echo "Building Frontend"
cd ./frontend
pnpm install
pnpm upgrade
pnpm run build
cp -r dist/* /app/frontend
cp -r app-images/* /app/frontend/images
echo "Built Frontend"

echo "Initializing Backend"
rm -rf /app/config/default.json
if [ ! -f /app/config/production.json ]; then
  cat <<'EOF' >/app/config/production.json
{
  "database": {
    "engine": "knex-native",
    "knex": {
      "client": "sqlite3",
      "connection": {
        "filename": "/data/database.sqlite"
      }
    }
  }
}
EOF
fi
cd /app
pnpm install
echo "Initialized Backend"

echo "Creating Service"
cat <<'EOF' >/lib/systemd/system/npm.service
[Unit]
Description=Nginx Proxy Manager
After=network.target
Wants=openresty.service

[Service]
Type=simple
Environment=NODE_ENV=production
ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge
ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
WorkingDirectory=/app
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
echo "Created Service"

#??motd_ssh
#??customize

echo "Starting Services"
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg
systemctl enable -q --now openresty
systemctl enable -q --now npm
echo "Started Services"

echo "Cleaning up"
rm -rf ../nginx-proxy-manager-*
systemctl restart openresty
apt-get -y autoremove
apt-get -y autoclean
echo "Cleaned"
echo "FINISH"

echo ""
echo ""

IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
PORT=81
echo "Open $IP:$PORT"
echo "Username: admin@example.com"
echo "Password: changeme"

__--There we have the salad --__ 🤗

<!-- gh-comment-id:2708810018 --> @B0F1B0 commented on GitHub (Mar 9, 2025): Hi netchild, if you have Proxmox, you can easy install `NPM - Nginx Proxy Manager` in an LXC Container with the `[Proxmox VE Helpder-Scripts`](https://community-scripts.github.io/ProxmoxVE/scripts?id=nginxproxymanager). Default settings: OS: Debian 12 CPU: 2vCPU RAM: 1GB HDD: 4GB The Proxmox VE Helper script executes [this ](https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/nginxproxymanager.sh)script, among others. I have adapted [this ](https://github.com/community-scripts/ProxmoxVE/blob/main/install/nginxproxymanager-install.sh)script that the **following script** will do perform a "bare metal" installation (Version 2.12.3). Since I am currently still on version 2.11.3 and would like to upgrade to 2.12.XXX, but version 2.12.3 (latest) is not working properly for me (streams not working), I also added version 2.12.0 till 2.12.2 as a comment in the script. Search for Keyword: `######LATETEST RELEASE` there you can comment out/in the necessary Version. ``` #!/usr/bin/env bash echo "Installing Dependencies" apt-get update apt-get -y install \ sudo \ mc \ curl \ gnupg \ make \ gcc \ g++ \ ca-certificates \ apache2-utils \ logrotate \ build-essential \ git echo "Installed Dependencies" echo "Installing Python Dependencies" apt-get install -y \ python3 \ python3-dev \ python3-pip \ python3-venv \ python3-cffi \ python3-certbot \ python3-certbot-dns-cloudflare rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED pip3 install certbot-dns-multi python3 -m venv /opt/certbot/ echo "Installed Python Dependencies" VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)" echo "Installing Openresty" wget -qO - https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg echo -e "deb http://openresty.org/package/debian bullseye openresty" >/etc/apt/sources.list.d/openresty.list apt-get update apt-get -y install openresty echo "Installed Openresty" echo "Installing Node.js" bash <(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh) source ~/.bashrc nvm install 16.20.2 ln -sf /root/.nvm/versions/node/v16.20.2/bin/node /usr/bin/node echo "Installed Node.js" echo "Installing pnpm" npm install -g pnpm@8.15 echo "Installed pnpm" ######LATETEST RELEASE RELEASE=$(curl -s https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz #RELEASE=2.12.2 ##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz #RELEASE=2.12.1 ##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz #RELEASE=2.12.0 ##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz cd ./nginx-proxy-manager-${RELEASE} echo "Downloaded Nginx Proxy Manager v${RELEASE}" echo "Setting up Environment" ln -sf /usr/bin/python3 /usr/bin/python ln -sf /usr/bin/certbot /opt/certbot/bin/certbot ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx ln -sf /usr/local/openresty/nginx/ /etc/nginx sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json #sed -i 's|"fork-me": ".*"|"fork-me": "Proxmox VE Helper-Scripts"|' frontend/js/i18n/messages.json #sed -i "s|https://github.com.*source=nginx-proxy-manager|https://helper-scripts.com|g" frontend/js/app/ui/footer/main.ejs sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf") for NGINX_CONF in $NGINX_CONFS; do sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF" done mkdir -p /var/www/html /etc/nginx/logs cp -r docker/rootfs/var/www/html/* /var/www/html/ cp -r docker/rootfs/etc/nginx/* /etc/nginx/ cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf rm -f /etc/nginx/conf.d/dev.conf mkdir -p /tmp/nginx/body \ /run/nginx \ /data/nginx \ /data/custom_ssl \ /data/logs \ /data/access \ /data/nginx/default_host \ /data/nginx/default_www \ /data/nginx/proxy_host \ /data/nginx/redirection_host \ /data/nginx/stream \ /data/nginx/dead_host \ /data/nginx/temp \ /var/lib/nginx/cache/public \ /var/lib/nginx/cache/private \ /var/cache/nginx/proxy_temp chmod -R 777 /var/cache/nginx chown root /tmp/nginx echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem &>/dev/null fi mkdir -p /app/global /app/frontend/images cp -r backend/* /app cp -r global/* /app/global echo "Set up Enviroment" echo "Building Frontend" cd ./frontend pnpm install pnpm upgrade pnpm run build cp -r dist/* /app/frontend cp -r app-images/* /app/frontend/images echo "Built Frontend" echo "Initializing Backend" rm -rf /app/config/default.json if [ ! -f /app/config/production.json ]; then cat <<'EOF' >/app/config/production.json { "database": { "engine": "knex-native", "knex": { "client": "sqlite3", "connection": { "filename": "/data/database.sqlite" } } } } EOF fi cd /app pnpm install echo "Initialized Backend" echo "Creating Service" cat <<'EOF' >/lib/systemd/system/npm.service [Unit] Description=Nginx Proxy Manager After=network.target Wants=openresty.service [Service] Type=simple Environment=NODE_ENV=production ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250 WorkingDirectory=/app Restart=on-failure [Install] WantedBy=multi-user.target EOF echo "Created Service" #??motd_ssh #??customize echo "Starting Services" sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg systemctl enable -q --now openresty systemctl enable -q --now npm echo "Started Services" echo "Cleaning up" rm -rf ../nginx-proxy-manager-* systemctl restart openresty apt-get -y autoremove apt-get -y autoclean echo "Cleaned" echo "FINISH" echo "" echo "" IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') PORT=81 echo "Open $IP:$PORT" echo "Username: admin@example.com" echo "Password: changeme" ``` `__--There we have the salad --__` 🤗
Author
Owner

@mokhos commented on GitHub (Mar 11, 2025):

Hi @B0F1B0,
may I ask if your setup works at all?

I'm using the latest version of NPM through the PVE Helper Scripts. But the proxy hosts are not working with my custom-ssl.
I even tried it without SSL, but the hosts are being redirects to https for some unknown reason and I get some ssl invalid end of file error.
I'm confused. I checked my configuration several times but I don't know if the problem is with the npm or not.

<!-- gh-comment-id:2714677858 --> @mokhos commented on GitHub (Mar 11, 2025): Hi @B0F1B0, may I ask if your setup works at all? I'm using the latest version of NPM through the PVE Helper Scripts. But the proxy hosts are not working with my custom-ssl. I even tried it without SSL, but the hosts are being redirects to https for some unknown reason and I get some ssl invalid end of file error. I'm confused. I checked my configuration several times but I don't know if the problem is with the npm or not.
Author
Owner

@B0F1B0 commented on GitHub (Mar 11, 2025):

Hi @B0F1B0, may I ask if your setup works at all?

I'm using the latest version of NPM through the PVE Helper Scripts. But the proxy hosts are not working with my custom-ssl. I even tried it without SSL, but the hosts are being redirects to https for some unknown reason and I get some ssl invalid end of file error. I'm confused. I checked my configuration several times but I don't know if the problem is with the npm or not.

Hi @mokhos

The latest PVE Helper Scripts install Version 2.12.3 and with that, i had no trouble with proxy-host and Let's Encrypt Certificates.
I did not use any custom ssl.
I had trouble with streams, so at the moment i am testing 2.12.2. There i had no trouble at the moment.

i even testet 2.12.3 without SSL-Certificates and it also worked, but only with firefox, because brave allways wants https.

<!-- gh-comment-id:2714889062 --> @B0F1B0 commented on GitHub (Mar 11, 2025): > Hi [@B0F1B0](https://github.com/B0F1B0), may I ask if your setup works at all? > > I'm using the latest version of NPM through the PVE Helper Scripts. But the proxy hosts are not working with my custom-ssl. I even tried it without SSL, but the hosts are being redirects to https for some unknown reason and I get some ssl invalid end of file error. I'm confused. I checked my configuration several times but I don't know if the problem is with the npm or not. Hi @mokhos The latest PVE Helper Scripts install Version 2.12.3 and with that, i had no trouble with proxy-host and Let's Encrypt Certificates. I did not use any custom ssl. I had trouble with streams, so at the moment i am testing 2.12.2. There i had no trouble at the moment. i even testet 2.12.3 without SSL-Certificates and it also worked, but only with firefox, because brave allways wants https.
Author
Owner

@o10g commented on GitHub (Apr 8, 2025):

Hi @B0F1B0
Could you be so kind to provide instructions how to downgrade the Proxmox installation to 2.12.2, as I need to proxying streams and the latest version has a problem with it - 500 Internal System Error:

structuredClone is not defined
<!-- gh-comment-id:2786063150 --> @o10g commented on GitHub (Apr 8, 2025): Hi @B0F1B0 Could you be so kind to provide instructions how to downgrade the Proxmox installation to 2.12.2, as I need to proxying streams and the latest version has a problem with it - `500 Internal System Error`: ``` structuredClone is not defined ```
Author
Owner

@B0F1B0 commented on GitHub (Apr 9, 2025):

Hi @o10g

I tried to downgrade NPM 2.12.3 to 2.12.2 but this does not work properly.I cant Login anymore.

The only solution I see here is to manually install NPM 2.12.2 in an LXC container as described above.

OS: Debian 12
CPU: 2vCPU
RAM: 1GB
HDD: 4GB

Here is the script from above, which explicitly installs NPM 2.12.2.

#!/bin/bash


echo "Installing Dependencies"
apt-get update
apt-get -y install \
  sudo \
  mc \
  curl \
  gnupg \
  make \
  gcc \
  g++ \
  ca-certificates \
  apache2-utils \
  logrotate \
  build-essential \
  git
echo "Installed Dependencies"

echo "Installing Python Dependencies"
apt-get install -y \
  python3 \
  python3-dev \
  python3-pip \
  python3-venv \
  python3-cffi \
  python3-certbot \
  python3-certbot-dns-cloudflare
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
pip3 install certbot-dns-multi
python3 -m venv /opt/certbot/
echo "Installed Python Dependencies"

VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"

echo "Installing Openresty"
wget -qO - https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg
echo -e "deb http://openresty.org/package/debian bullseye openresty" >/etc/apt/sources.list.d/openresty.list
apt-get update
apt-get -y install openresty
echo "Installed Openresty"

echo "Installing Node.js"
bash <(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh)
source ~/.bashrc
nvm install 16.20.2
ln -sf /root/.nvm/versions/node/v16.20.2/bin/node /usr/bin/node
echo "Installed Node.js"

echo "Installing pnpm"
npm install -g pnpm@8.15
echo "Installed pnpm"

######LATETEST RELEASE
#RELEASE=$(curl -s https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
#  grep "tag_name" |
#  awk '{print substr($2, 3, length($2)-4) }')
#wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz

RELEASE=2.12.2
wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz
#RELEASE=2.12.1
##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz
#RELEASE=2.12.0
##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz


cd ./nginx-proxy-manager-${RELEASE}
echo "Downloaded Nginx Proxy Manager v${RELEASE}"

echo "Setting up Environment"
ln -sf /usr/bin/python3 /usr/bin/python
ln -sf /usr/bin/certbot /opt/certbot/bin/certbot
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
ln -sf /usr/local/openresty/nginx/ /etc/nginx

sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json
sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json

#sed -i 's|"fork-me": ".*"|"fork-me": "Proxmox VE Helper-Scripts"|' frontend/js/i18n/messages.json
#sed -i "s|https://github.com.*source=nginx-proxy-manager|https://helper-scripts.com|g" frontend/js/app/ui/footer/main.ejs
sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf")
for NGINX_CONF in $NGINX_CONFS; do
  sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
done

mkdir -p /var/www/html /etc/nginx/logs
cp -r docker/rootfs/var/www/html/* /var/www/html/
cp -r docker/rootfs/etc/nginx/* /etc/nginx/
cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager
ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
rm -f /etc/nginx/conf.d/dev.conf

mkdir -p /tmp/nginx/body \
  /run/nginx \
  /data/nginx \
  /data/custom_ssl \
  /data/logs \
  /data/access \
  /data/nginx/default_host \
  /data/nginx/default_www \
  /data/nginx/proxy_host \
  /data/nginx/redirection_host \
  /data/nginx/stream \
  /data/nginx/dead_host \
  /data/nginx/temp \
  /var/lib/nginx/cache/public \
  /var/lib/nginx/cache/private \
  /var/cache/nginx/proxy_temp

chmod -R 777 /var/cache/nginx
chown root /tmp/nginx

echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf

if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
  openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem &>/dev/null
fi

mkdir -p /app/global /app/frontend/images
cp -r backend/* /app
cp -r global/* /app/global
echo "Set up Enviroment"

echo "Building Frontend"
cd ./frontend
pnpm install
pnpm upgrade
pnpm run build
cp -r dist/* /app/frontend
cp -r app-images/* /app/frontend/images
echo "Built Frontend"

echo "Initializing Backend"
rm -rf /app/config/default.json
if [ ! -f /app/config/production.json ]; then
  cat <<'EOF' >/app/config/production.json
{
  "database": {
    "engine": "knex-native",
    "knex": {
      "client": "sqlite3",
      "connection": {
        "filename": "/data/database.sqlite"
      }
    }
  }
}
EOF
fi
cd /app
pnpm install
echo "Initialized Backend"

echo "Creating Service"
cat <<'EOF' >/lib/systemd/system/npm.service
[Unit]
Description=Nginx Proxy Manager
After=network.target
Wants=openresty.service

[Service]
Type=simple
Environment=NODE_ENV=production
ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge
ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
WorkingDirectory=/app
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
echo "Created Service"

#??motd_ssh
#??customize

echo "Starting Services"
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg
systemctl enable -q --now openresty
systemctl enable -q --now npm
echo "Started Services"

echo "Cleaning up"
rm -rf ../nginx-proxy-manager-*
systemctl restart openresty
apt-get -y autoremove
apt-get -y autoclean
echo "Cleaned"
echo "FINISH"

echo ""
echo ""

IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
PORT=81
echo "Open $IP:$PORT"
echo "Username: admin@example.com"
echo "Password: changeme"
<!-- gh-comment-id:2790121881 --> @B0F1B0 commented on GitHub (Apr 9, 2025): Hi @o10g I tried to downgrade NPM 2.12.3 to 2.12.2 but this does not work properly.I cant Login anymore. The only solution I see here is to **manually** install NPM 2.12.2 in an LXC container as described above. OS: Debian 12 CPU: 2vCPU RAM: 1GB HDD: 4GB Here is the script from above, which explicitly installs NPM 2.12.2. ``` #!/bin/bash echo "Installing Dependencies" apt-get update apt-get -y install \ sudo \ mc \ curl \ gnupg \ make \ gcc \ g++ \ ca-certificates \ apache2-utils \ logrotate \ build-essential \ git echo "Installed Dependencies" echo "Installing Python Dependencies" apt-get install -y \ python3 \ python3-dev \ python3-pip \ python3-venv \ python3-cffi \ python3-certbot \ python3-certbot-dns-cloudflare rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED pip3 install certbot-dns-multi python3 -m venv /opt/certbot/ echo "Installed Python Dependencies" VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)" echo "Installing Openresty" wget -qO - https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg echo -e "deb http://openresty.org/package/debian bullseye openresty" >/etc/apt/sources.list.d/openresty.list apt-get update apt-get -y install openresty echo "Installed Openresty" echo "Installing Node.js" bash <(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh) source ~/.bashrc nvm install 16.20.2 ln -sf /root/.nvm/versions/node/v16.20.2/bin/node /usr/bin/node echo "Installed Node.js" echo "Installing pnpm" npm install -g pnpm@8.15 echo "Installed pnpm" ######LATETEST RELEASE #RELEASE=$(curl -s https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | # grep "tag_name" | # awk '{print substr($2, 3, length($2)-4) }') #wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz RELEASE=2.12.2 wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz #RELEASE=2.12.1 ##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz #RELEASE=2.12.0 ##wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz cd ./nginx-proxy-manager-${RELEASE} echo "Downloaded Nginx Proxy Manager v${RELEASE}" echo "Setting up Environment" ln -sf /usr/bin/python3 /usr/bin/python ln -sf /usr/bin/certbot /opt/certbot/bin/certbot ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx ln -sf /usr/local/openresty/nginx/ /etc/nginx sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json #sed -i 's|"fork-me": ".*"|"fork-me": "Proxmox VE Helper-Scripts"|' frontend/js/i18n/messages.json #sed -i "s|https://github.com.*source=nginx-proxy-manager|https://helper-scripts.com|g" frontend/js/app/ui/footer/main.ejs sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf") for NGINX_CONF in $NGINX_CONFS; do sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF" done mkdir -p /var/www/html /etc/nginx/logs cp -r docker/rootfs/var/www/html/* /var/www/html/ cp -r docker/rootfs/etc/nginx/* /etc/nginx/ cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf rm -f /etc/nginx/conf.d/dev.conf mkdir -p /tmp/nginx/body \ /run/nginx \ /data/nginx \ /data/custom_ssl \ /data/logs \ /data/access \ /data/nginx/default_host \ /data/nginx/default_www \ /data/nginx/proxy_host \ /data/nginx/redirection_host \ /data/nginx/stream \ /data/nginx/dead_host \ /data/nginx/temp \ /var/lib/nginx/cache/public \ /var/lib/nginx/cache/private \ /var/cache/nginx/proxy_temp chmod -R 777 /var/cache/nginx chown root /tmp/nginx echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem &>/dev/null fi mkdir -p /app/global /app/frontend/images cp -r backend/* /app cp -r global/* /app/global echo "Set up Enviroment" echo "Building Frontend" cd ./frontend pnpm install pnpm upgrade pnpm run build cp -r dist/* /app/frontend cp -r app-images/* /app/frontend/images echo "Built Frontend" echo "Initializing Backend" rm -rf /app/config/default.json if [ ! -f /app/config/production.json ]; then cat <<'EOF' >/app/config/production.json { "database": { "engine": "knex-native", "knex": { "client": "sqlite3", "connection": { "filename": "/data/database.sqlite" } } } } EOF fi cd /app pnpm install echo "Initialized Backend" echo "Creating Service" cat <<'EOF' >/lib/systemd/system/npm.service [Unit] Description=Nginx Proxy Manager After=network.target Wants=openresty.service [Service] Type=simple Environment=NODE_ENV=production ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250 WorkingDirectory=/app Restart=on-failure [Install] WantedBy=multi-user.target EOF echo "Created Service" #??motd_ssh #??customize echo "Starting Services" sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg systemctl enable -q --now openresty systemctl enable -q --now npm echo "Started Services" echo "Cleaning up" rm -rf ../nginx-proxy-manager-* systemctl restart openresty apt-get -y autoremove apt-get -y autoclean echo "Cleaned" echo "FINISH" echo "" echo "" IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') PORT=81 echo "Open $IP:$PORT" echo "Username: admin@example.com" echo "Password: changeme" ```
Author
Owner

@Wolfhound905 commented on GitHub (Apr 28, 2025):

@o10g @B0F1B0

Streams is having an issue because you need a higher version of node. 17.9.1 works.

The error is structuredClone is not defined, which was a function added in node v17. So make sure to update npm.service to use like nvm 17 path and not usr/bin/node. Let me know if you need help, this got my streams working on Proxy Manager v2.12.3

<!-- gh-comment-id:2835991890 --> @Wolfhound905 commented on GitHub (Apr 28, 2025): @o10g @B0F1B0 Streams is having an issue because you need a higher version of node. 17.9.1 works. The error is `structuredClone is not defined`, which was a function added in node v17. So make sure to update `npm.service` to use like nvm 17 path and not usr/bin/node. Let me know if you need help, this got my streams working on Proxy Manager v2.12.3
Author
Owner

@PontyJohnty commented on GitHub (May 12, 2025):

I am running 2.12.3 from proxmox helper scripts. on an unpriv LXC on Proxmox.

If this is of any help i did the following to get streams working.

nvm install node
nvm use node
nvm alias default node

confirmed node version

node -v

for me it was v24.0.1

then i updated the npm.service unit ( /lib/systemd/system/npm.service ) to the following


[Unit]
Description=Nginx Proxy Manager
After=network.target
Wants=openresty.service

[Service]
Type=simple
Environment=NODE_ENV=production
ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge
ExecStart=/root/.nvm/versions/node/v24.0.1/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
# ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
WorkingDirectory=/app
Restart=on-failure

[Install]
WantedBy=multi-user.target

Note the former ExecStart is commented out for reference.

Ensure your node version matches that on the ExecStart line.

systemctl daemon-reload
systemctl restart npm.service

I was then able to create streams.

<!-- gh-comment-id:2873893183 --> @PontyJohnty commented on GitHub (May 12, 2025): I am running 2.12.3 from [proxmox helper scripts.](https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/nginxproxymanager-install.sh) on an unpriv LXC on Proxmox. If this is of any help i did the following to get streams working. ``` nvm install node nvm use node nvm alias default node ``` confirmed node version `node -v` for me it was v24.0.1 then i updated the npm.service unit ( /lib/systemd/system/npm.service ) to the following ``` [Unit] Description=Nginx Proxy Manager After=network.target Wants=openresty.service [Service] Type=simple Environment=NODE_ENV=production ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge ExecStart=/root/.nvm/versions/node/v24.0.1/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250 # ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250 WorkingDirectory=/app Restart=on-failure [Install] WantedBy=multi-user.target ``` Note the former ExecStart is commented out for reference. Ensure your node version matches that on the ExecStart line. ``` systemctl daemon-reload systemctl restart npm.service ``` I was then able to create streams.
Author
Owner

@LohmarCoUk commented on GitHub (Nov 11, 2025):

I have to agree with 'not the entire world is docker' - for example I use a Ubuntu LXD/LXC environment. I could run a docker or podman container inside my LXC container but what is the point of having a box in a box?
I'm considering to publish a git-repository for 'Nginx Proxy Manager on Bare Metal' - share your thoughts on this.

Here my Script (NPM Version 2.13.2), it should work on Bare Metal / VMs / and Container.

#!/usr/bin/env bash
#
# Nginx Proxy Manager LXD Installation Script Version 0.8
# Author: AI[den] ;-)
# Date: 2025-11-08
# Description: Installs Nginx Proxy Manager in an LXC container for LXD environments
# License: GPL3 | https://www.gnu.org/licenses/gpl.txt
# Source: https://community-scripts.github.io/ProxmoxVE/scripts?id=nginxproxymanager
# Source: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/4420


set -e  # Exit on any error

echo "Installing Dependencies"
apt-get update
apt-get -y install \
  sudo \
  nano \
  tree \
  mc \
  curl \
  wget \
  gnupg \
  ca-certificates \
  make \
  gcc \
  g++ \
  apache2-utils \
  logrotate \
  build-essential \
  git \
  golang-go

echo "Installing Node.js 22.x"
# Install Node.js 22.x from NodeSource
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get update
apt-get install -y nodejs

echo "Installing yarn"
npm install -g yarn

echo "Installing Python Dependencies"
apt-get install -y \
  python3 \
  python3-dev \
  python3-pip \
  python3-venv \
  python3-cffi \
  python3-certbot \
  python3-certbot-dns-cloudflare

# Remove externally-managed restriction for pip
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED 2>/dev/null || true

# Install certbot-dns-multi with build dependencies
apt-get install -y pkg-config libssl-dev
pip3 install --break-system-packages certbot-dns-multi

echo "Installing Openresty"
# Import GPG key and add repository
wget -O - https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty.gpg

# Get the codename dynamically
codename=$(grep -Po 'VERSION="[0-9]+ \(\K[^)]+' /etc/os-release)

echo "deb http://openresty.org/package/debian $codename openresty" \
    | tee /etc/apt/sources.list.d/openresty.list

# Update and install openresty
apt-get update
apt-get -y install openresty

###### LATEST RELEASE
RELEASE='2.13.2'
RELEASE_FILE="v${RELEASE}.tar.gz"

echo "Downloading Nginx Proxy Manager v${RELEASE}"
cd /root
# Clean up any previous failed attempts
rm -rf nginx-proxy-manager-* 2>/dev/null || true

# Use the correct URL
wget -q https://github.com/NginxProxyManager/nginx-proxy-manager/archive/refs/tags/${RELEASE_FILE} -O nginx-proxy-manager-${RELEASE}.tar.gz

# Check if download was successful
if [ ! -f "nginx-proxy-manager-${RELEASE}.tar.gz" ]; then
    echo "ERROR: Download failed!"
    exit 1
fi

echo "Extracting NPM..."
tar -xzf nginx-proxy-manager-${RELEASE}.tar.gz

# Check if extraction was successful
if [ ! -d "nginx-proxy-manager-${RELEASE}" ]; then
    echo "ERROR: Extraction failed!"
    exit 1
fi

cd nginx-proxy-manager-${RELEASE}
echo "Successfully downloaded and extracted Nginx Proxy Manager v${RELEASE}"

echo "Setting up Environment"
ln -sf /usr/bin/python3 /usr/bin/python
# FIX: Remove the problematic certbot symlink - it's not needed since certbot is already in PATH
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
ln -sf /usr/local/openresty/nginx/ /etc/nginx

# Fix version in package.json files
if [ -f "backend/package.json" ]; then
  sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json
fi

if [ -f "frontend/package.json" ]; then
  sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json
fi

# Update nginx configuration
if [ -f "docker/rootfs/etc/nginx/nginx.conf" ]; then
  sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
  sed -i 's/user npm/user root/g' docker/rootfs/etc/nginx/nginx.conf
fi

# Update nginx include paths
NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf")
for NGINX_CONF in $NGINX_CONFS; do
  sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
done

# Create directories and copy files
mkdir -p /var/www/html /etc/nginx/logs

if [ -d "docker/rootfs/var/www/html" ]; then
  cp -r docker/rootfs/var/www/html/* /var/www/html/ 2>/dev/null || true
fi

if [ -d "docker/rootfs/etc/nginx" ]; then
  cp -r docker/rootfs/etc/nginx/* /etc/nginx/ 2>/dev/null || true
fi

[ -f "docker/rootfs/etc/letsencrypt.ini" ] && cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
[ -f "docker/rootfs/etc/logrotate.d/nginx-proxy-manager" ] && cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager

ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf 2>/dev/null || true
rm -f /etc/nginx/conf.d/dev.conf 2>/dev/null || true

# Create necessary directories
mkdir -p /tmp/nginx/body \
  /run/nginx \
  /data/nginx \
  /data/custom_ssl \
  /data/logs \
  /data/access \
  /data/nginx/default_host \
  /data/nginx/default_www \
  /data/nginx/proxy_host \
  /data/nginx/redirection_host \
  /data/nginx/stream \
  /data/nginx/dead_host \
  /data/nginx/temp \
  /var/lib/nginx/cache/public \
  /var/lib/nginx/cache/private \
  /var/cache/nginx/proxy_temp

chmod -R 777 /var/cache/nginx
chown root /tmp/nginx

# Create resolvers config
mkdir -p /etc/nginx/conf.d/include
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf

# Generate dummy certificate if needed
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
  openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
    -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" \
    -keyout /data/nginx/dummykey.pem \
    -out /data/nginx/dummycert.pem &>/dev/null
fi

# Copy application files
mkdir -p /app/frontend/images
[ -d "backend" ] && cp -r backend/* /app/ 2>/dev/null || true
echo "Set up Environment"

echo "Building Frontend"
if [ -d "frontend" ]; then
  cd frontend

  # Replace node-sass with sass (key insight from Proxmox script)
  if [ -f "package.json" ]; then
    sed -E -i 's/"node-sass" *: *"([^"]*)"/"sass": "\1"/g' package.json
  fi

  # Set Node.js options for build
  export NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider"

  # Install dependencies and build with yarn
  yarn install --network-timeout 600000
  yarn build

  mkdir -p /app/frontend
  cp -r dist/* /app/frontend/ 2>/dev/null || true
  [ -d "public/images" ] && cp -r public/images/* /app/frontend/images/ 2>/dev/null || true
  cd ..
else
  echo "WARNING: frontend directory not found"
fi
echo "Built Frontend"

echo "Initializing Backend"
mkdir -p /app/config
rm -rf /app/config/default.json 2>/dev/null || true
if [ ! -f /app/config/production.json ]; then
  cat <<'EOF' >/app/config/production.json
{
  "database": {
    "engine": "knex-native",
    "knex": {
      "client": "sqlite3",
      "connection": {
        "filename": "/data/database.sqlite"
      }
    }
  }
}
EOF
fi

if [ -d "/app" ]; then
  cd /app
  yarn install --network-timeout 600000
else
  echo "WARNING: /app directory not found"
fi
echo "Initialized Backend"

echo "Creating Service"
mkdir -p /lib/systemd/system
cat <<'EOF' >/lib/systemd/system/npm.service
[Unit]
Description=Nginx Proxy Manager
After=network.target
Wants=openresty.service

[Service]
Type=simple
Environment=NODE_ENV=production
ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge
ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
WorkingDirectory=/app
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

echo "Starting Services"
# Update nginx configuration
if [ -f "/usr/local/openresty/nginx/conf/nginx.conf" ]; then
  sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
fi

if [ -f "/etc/logrotate.d/nginx-proxy-manager" ]; then
  sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
fi

systemctl enable -q openresty
systemctl enable -q npm
systemctl stop openresty 2>/dev/null || true
systemctl stop npm 2>/dev/null || true
systemctl start openresty
systemctl start npm

echo "Cleaning up"
cd /root
rm -rf nginx-proxy-manager-* 2>/dev/null || true
apt-get -y autoremove
apt-get -y autoclean

echo "FINISH"

echo ""
echo ""

IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)
PORT=81
echo "Open http://$IP:$PORT"
<!-- gh-comment-id:3515348770 --> @LohmarCoUk commented on GitHub (Nov 11, 2025): I have to agree with '**not the entire world is docker**' - for example I use a Ubuntu LXD/LXC environment. I could run a docker or podman container inside my LXC container but what is the point of having a box in a box? I'm considering to publish a git-repository for 'Nginx Proxy Manager on Bare Metal' - share your thoughts on this. **Here my Script (NPM Version 2.13.2), it should work on Bare Metal / VMs / and Container.** ```sh #!/usr/bin/env bash # # Nginx Proxy Manager LXD Installation Script Version 0.8 # Author: AI[den] ;-) # Date: 2025-11-08 # Description: Installs Nginx Proxy Manager in an LXC container for LXD environments # License: GPL3 | https://www.gnu.org/licenses/gpl.txt # Source: https://community-scripts.github.io/ProxmoxVE/scripts?id=nginxproxymanager # Source: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/4420 set -e # Exit on any error echo "Installing Dependencies" apt-get update apt-get -y install \ sudo \ nano \ tree \ mc \ curl \ wget \ gnupg \ ca-certificates \ make \ gcc \ g++ \ apache2-utils \ logrotate \ build-essential \ git \ golang-go echo "Installing Node.js 22.x" # Install Node.js 22.x from NodeSource curl -fsSL https://deb.nodesource.com/setup_22.x | bash - apt-get update apt-get install -y nodejs echo "Installing yarn" npm install -g yarn echo "Installing Python Dependencies" apt-get install -y \ python3 \ python3-dev \ python3-pip \ python3-venv \ python3-cffi \ python3-certbot \ python3-certbot-dns-cloudflare # Remove externally-managed restriction for pip rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED 2>/dev/null || true # Install certbot-dns-multi with build dependencies apt-get install -y pkg-config libssl-dev pip3 install --break-system-packages certbot-dns-multi echo "Installing Openresty" # Import GPG key and add repository wget -O - https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty.gpg # Get the codename dynamically codename=$(grep -Po 'VERSION="[0-9]+ \(\K[^)]+' /etc/os-release) echo "deb http://openresty.org/package/debian $codename openresty" \ | tee /etc/apt/sources.list.d/openresty.list # Update and install openresty apt-get update apt-get -y install openresty ###### LATEST RELEASE RELEASE='2.13.2' RELEASE_FILE="v${RELEASE}.tar.gz" echo "Downloading Nginx Proxy Manager v${RELEASE}" cd /root # Clean up any previous failed attempts rm -rf nginx-proxy-manager-* 2>/dev/null || true # Use the correct URL wget -q https://github.com/NginxProxyManager/nginx-proxy-manager/archive/refs/tags/${RELEASE_FILE} -O nginx-proxy-manager-${RELEASE}.tar.gz # Check if download was successful if [ ! -f "nginx-proxy-manager-${RELEASE}.tar.gz" ]; then echo "ERROR: Download failed!" exit 1 fi echo "Extracting NPM..." tar -xzf nginx-proxy-manager-${RELEASE}.tar.gz # Check if extraction was successful if [ ! -d "nginx-proxy-manager-${RELEASE}" ]; then echo "ERROR: Extraction failed!" exit 1 fi cd nginx-proxy-manager-${RELEASE} echo "Successfully downloaded and extracted Nginx Proxy Manager v${RELEASE}" echo "Setting up Environment" ln -sf /usr/bin/python3 /usr/bin/python # FIX: Remove the problematic certbot symlink - it's not needed since certbot is already in PATH ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx ln -sf /usr/local/openresty/nginx/ /etc/nginx # Fix version in package.json files if [ -f "backend/package.json" ]; then sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json fi if [ -f "frontend/package.json" ]; then sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json fi # Update nginx configuration if [ -f "docker/rootfs/etc/nginx/nginx.conf" ]; then sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf sed -i 's/user npm/user root/g' docker/rootfs/etc/nginx/nginx.conf fi # Update nginx include paths NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf") for NGINX_CONF in $NGINX_CONFS; do sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF" done # Create directories and copy files mkdir -p /var/www/html /etc/nginx/logs if [ -d "docker/rootfs/var/www/html" ]; then cp -r docker/rootfs/var/www/html/* /var/www/html/ 2>/dev/null || true fi if [ -d "docker/rootfs/etc/nginx" ]; then cp -r docker/rootfs/etc/nginx/* /etc/nginx/ 2>/dev/null || true fi [ -f "docker/rootfs/etc/letsencrypt.ini" ] && cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini [ -f "docker/rootfs/etc/logrotate.d/nginx-proxy-manager" ] && cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf 2>/dev/null || true rm -f /etc/nginx/conf.d/dev.conf 2>/dev/null || true # Create necessary directories mkdir -p /tmp/nginx/body \ /run/nginx \ /data/nginx \ /data/custom_ssl \ /data/logs \ /data/access \ /data/nginx/default_host \ /data/nginx/default_www \ /data/nginx/proxy_host \ /data/nginx/redirection_host \ /data/nginx/stream \ /data/nginx/dead_host \ /data/nginx/temp \ /var/lib/nginx/cache/public \ /var/lib/nginx/cache/private \ /var/cache/nginx/proxy_temp chmod -R 777 /var/cache/nginx chown root /tmp/nginx # Create resolvers config mkdir -p /etc/nginx/conf.d/include echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf # Generate dummy certificate if needed if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \ -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" \ -keyout /data/nginx/dummykey.pem \ -out /data/nginx/dummycert.pem &>/dev/null fi # Copy application files mkdir -p /app/frontend/images [ -d "backend" ] && cp -r backend/* /app/ 2>/dev/null || true echo "Set up Environment" echo "Building Frontend" if [ -d "frontend" ]; then cd frontend # Replace node-sass with sass (key insight from Proxmox script) if [ -f "package.json" ]; then sed -E -i 's/"node-sass" *: *"([^"]*)"/"sass": "\1"/g' package.json fi # Set Node.js options for build export NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider" # Install dependencies and build with yarn yarn install --network-timeout 600000 yarn build mkdir -p /app/frontend cp -r dist/* /app/frontend/ 2>/dev/null || true [ -d "public/images" ] && cp -r public/images/* /app/frontend/images/ 2>/dev/null || true cd .. else echo "WARNING: frontend directory not found" fi echo "Built Frontend" echo "Initializing Backend" mkdir -p /app/config rm -rf /app/config/default.json 2>/dev/null || true if [ ! -f /app/config/production.json ]; then cat <<'EOF' >/app/config/production.json { "database": { "engine": "knex-native", "knex": { "client": "sqlite3", "connection": { "filename": "/data/database.sqlite" } } } } EOF fi if [ -d "/app" ]; then cd /app yarn install --network-timeout 600000 else echo "WARNING: /app directory not found" fi echo "Initialized Backend" echo "Creating Service" mkdir -p /lib/systemd/system cat <<'EOF' >/lib/systemd/system/npm.service [Unit] Description=Nginx Proxy Manager After=network.target Wants=openresty.service [Service] Type=simple Environment=NODE_ENV=production ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250 WorkingDirectory=/app Restart=on-failure [Install] WantedBy=multi-user.target EOF echo "Starting Services" # Update nginx configuration if [ -f "/usr/local/openresty/nginx/conf/nginx.conf" ]; then sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf fi if [ -f "/etc/logrotate.d/nginx-proxy-manager" ]; then sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager fi systemctl enable -q openresty systemctl enable -q npm systemctl stop openresty 2>/dev/null || true systemctl stop npm 2>/dev/null || true systemctl start openresty systemctl start npm echo "Cleaning up" cd /root rm -rf nginx-proxy-manager-* 2>/dev/null || true apt-get -y autoremove apt-get -y autoclean echo "FINISH" echo "" echo "" IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1) PORT=81 echo "Open http://$IP:$PORT" ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/nginx-proxy-manager-NginxProxyManager#2829
No description provided.