Merge pull request #146 from ej52/develop

refactor: Overhaul create and install scripts
This commit is contained in:
Elton Renda
2023-12-04 10:16:34 +02:00
committed by GitHub
14 changed files with 960 additions and 784 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -2,6 +2,58 @@
Some useful proxmox scripts... Some useful proxmox scripts...
## Scripts ## Usage
[Nginx Proxy Manager](https://github.com/ej52/proxmox/tree/main/lxc/nginx-proxy-manager) To create a new LXC container on Proxmox and setup a app to run inside of it, run the following in a SSH connection or the Proxmox web shell.
***Tested with:*** _proxmox 7.1+, alpine 3.12+, debian 11+, Ubuntu 18+_
```bash
curl -sL https://raw.githubusercontent.com/ej52/proxmox/main/create.sh | bash -s
```
### Command line arguments
| argument | default | description |
|--------------------|----------------------|--------------------------------------------------------|
| --app | nginx-proxy-manager | application to install |
| --id | $nextid | container id |
| --os | alpine | OS distribution to install |
| --os-version | latest | OS version to install |
| --bridge | vmbr0 | bridge used for eth0 |
| --cores | 1 | number of cpu cores |
| --disksize | 4G | size of disk |
| --hostname | value of --app | hostname of the container |
| --memory | 512 | amount of memory |
| --storage | local-lvm | storage location for container disk |
| --templates | local | storage location for templates |
| --swap | 0 | amount of SWAP |
| --cleanup | false | Remove dev dependencies after install |
you can set these parameters by appending ` -- <parameter> <value>` like:
```bash
curl -sL https://raw.githubusercontent.com/ej52/proxmox/main/create.sh | bash -s -- --app nginx-proxy-manager --cleanup
```
### Console
There is no login required to access the console from the Proxmox web UI. If you are presented with a blank screen, press `CTRL + C` to generate a prompt.
## Alternative Usage
If you are not using proxmox or want to install a app on a existing install, you can run the setup script itself.
***Note:*** _Only Alpine, Debian and Ubuntu are currently supported_
```sh
sh -c "$(wget --no-cache -qO- https://raw.githubusercontent.com/ej52/proxmox/main/install.sh)" -s --app nginx-proxy-manager
sh -c "$(wget --no-cache -qO- http://10.0.1.21:1337/install.sh)" -s --app nginx-proxy-manager --clean
```
## Applications
[Nginx Proxy Manager](https://github.com/ej52/proxmox/tree/main/apps/nginx-proxy-manager)
## Thanks
- [whiskerz007](https://github.com/whiskerz007?tab=repositories)

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
pms_header() {
clear
cat <<"EOF"
_ __ _ ____ __ ___
/ | / /___ _(_)___ _ __ / __ \_________ __ ____ __ / |/ /___ _____ ____ _____ ____ _____
/ |/ / __ / / __ \| |/_/ / /_/ / ___/ __ \| |/_/ / / / / /|_/ / __ / __ \/ __ / __ / _ \/ ___/
/ /| / /_/ / / / / /> < / ____/ / / /_/ /> </ /_/ / / / / / /_/ / / / / /_/ / /_/ / __/ /
/_/ |_/\__, /_/_/ /_/_/|_| /_/ /_/ \____/_/|_|\__, / /_/ /_/\__,_/_/ /_/\__,_/\__, /\___/_/
/____/ /____/ /____/
EOF
}
EPS_SUPPORTED_DISTROS="alpine debian ubuntu"
# Override default CT settings
EPS_CT_CPU_CORES=${EPS_CT_CPU_CORES:-1}
EPS_CT_DISK_SIZE=${EPS_CT_DISK_SIZE:-4}
EPS_CT_MEMORY=${EPS_CT_MEMORY:-512}
EPS_CT_SWAP=${EPS_CT_SWAP:-0}
# NPM package versions
NODE_VERSION="v16.20.2"
YARN_VERSION="1.22.19"
RUST_VERSION="1.74.0"
EPS_SERVICE_FILE=/etc/init.d/npm
EPS_SERVICE_DATA="#!/sbin/openrc-run\ndescription=\"Nginx Proxy Manager\"\n\ncommand=\"/usr/local/bin/node\"\ncommand_args=\"index.js --abort_on_uncaught_exception --max_old_space_size=250\"\ncommand_background=\"yes\"\ndirectory=\"/app\"\n\npidfile=\"/var/run/npm.pid\"\noutput_log=\"/var/log/npm.log\"\nerror_log=\"/var/log/npm.err\"\n\ndepends () {\n before openresty\n}\n\nstart_pre() {\n mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge\n export NODE_ENV=production\n}\n\nstop() {\n pkill -9 -f node\n return 0\n}\n\nrestart() {\n \$0 stop\n \$0 start\n}"
EPS_DEPENDENCIES="gcc g++ make musl-dev openssl-dev git libffi-dev python3-dev"
if [ "$EPS_OS_DISTRO" = "debian" -o "$EPS_OS_DISTRO" = "ubuntu" ]; then
EPS_SERVICE_FILE=/lib/systemd/system/npm.service
EPS_SERVICE_DATA="[Unit]\nDescription=Nginx Proxy Manager\nAfter=network.target\nWants=openresty.service\n\n[Service]\nType=simple\nEnvironment=NODE_ENV=production\nExecStartPre=-/bin/mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge\nExecStart=/usr/local/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250\nWorkingDirectory=/app\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target"
EPS_DEPENDENCIES="build-essential libssl-dev git libffi-dev python3-dev"
fi
lxc_checks() {
if [ "$EPS_CT_DISK_SIZE" -lt 4 ]; then
log "warn" "This LXC container requires at least 4GB of disk space" 1
fi
}

View File

@@ -0,0 +1,309 @@
#!/usr/bin/env bash
EPS_BASE_URL=${EPS_BASE_URL:-}
EPS_OS_DISTRO=${EPS_OS_DISTRO:-}
EPS_UTILS=${EPS_UTILS:-}
EPS_APP_CONFIG=${EPS_APP_CONFIG:-}
EPS_CLEANUP=${EPS_CLEANUP:-false}
EPS_CT_INSTALL=${EPS_CT_INSTALL:-false}
if [ -z "$EPS_BASE_URL" -o -z "$EPS_OS_DISTRO" -o -z "$EPS_UTILS" -o -z "$EPS_APP_CONFIG" ]; then
printf "Script looded incorrectly!\n\n";
exit 1;
fi
source <(echo -n "$EPS_UTILS")
source <(echo -n "$EPS_APP_CONFIG")
source <(wget --no-cache -qO- ${EPS_BASE_URL}/utils/${EPS_OS_DISTRO}.sh)
pms_bootstrap
pms_settraps
if [ $EPS_CT_INSTALL = false ]; then
pms_header
fi
EPS_OS_ARCH=$(os_arch)
EPS_OS_CODENAME=$(os_codename)
EPS_OS_VERSION=${EPS_OS_VERSION:-$(os_version)}
# Check for previous install
if [ -f "$EPS_SERVICE_FILE" ]; then
step_start "Previous Installation" "Cleaning" "Cleaned"
svc_stop npm
svc_stop openresty
# Remove old installation files
rm -rf /app \
/var/www/html \
/etc/nginx \
/var/log/nginx \
/var/lib/nginx \
/var/cache/nginx \
/opt/certbot/bin/certbot
fi
step_start "Operating System" "Updating" "Updated"
pkg_update
pkg_upgrade
step_start "Dependencies" "Installing" "Installed"
# Remove potential conflicting depenedencies
pkg_del nodejs npm yarn *certbot rust* cargo*
# Install required depenedencies
pkg_add ca-certificates gnupg openssl apache2-utils logrotate $EPS_DEPENDENCIES
step_start "Rust" "Installing" "Installed"
_rustArch=""
_rustClibtype="gnu"
if [ "$EPS_OS_DISTRO" = "alpine" ]; then
_rustClibtype="musl"
fi
case "${EPS_OS_ARCH##*-}" in
amd64 | x86_64) _rustArch="x86_64-unknown-linux-${_rustClibtype}";;
arm64 | aarch64) _rustArch="aarch64-unknown-linux-${_rustClibtype}";;
armhf) _rustArch="armv7-unknown-linux-gnueabihf";;
i386 | x86) _rustArch="i686-unknown-linux-${_rustClibtype}";;
*) step_end "Architecture not supported: ${CLR_CYB}$EPS_OS_ARCH${CLR}" 1;;
esac
if [ "$EPS_OS_DISTRO" = "alpine" ]; then
if [ "$EPS_OS_ARCH" != "x86_64" -a "$EPS_OS_ARCH" != "aarch64" ]; then
step_end "Architecture not supported: ${CLR_CYB}$EPS_OS_ARCH${CLR}" 1
fi
fi
os_fetch -O ./rustup-init https://static.rust-lang.org/rustup/archive/1.26.0/$_rustArch/rustup-init
chmod +x ./rustup-init
./rustup-init -q -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host $_rustArch &>$__OUTPUT
rm ./rustup-init
ln -sf ~/.cargo/bin/cargo /usr//bin/cargo
ln -sf ~/.cargo/bin/rustc /usr/bin/rustc
ln -sf ~/.cargo/bin/rustup /usr/bin/rustup
step_end "Rust ${CLR_CYB}v$RUST_VERSION${CLR} ${CLR_GN}Installed"
step_start "Python"
export PIP_ROOT_USER_ACTION=ignore
# Remove old venv and global pip packages
rm -rf /opt/certbot/ /usr/bin/certbot
if [ "$(command -v pip)" ]; then
pip uninstall -q -y cryptography cffi certbot tldextract --break-system-packages &>$__OUTPUT
fi
# Remove potential conflicting depenedencies
pkg_del *3-pip *3-cffi *3-cryptography *3-tldextract *3-distutils *3-venv
# Install python depenedencies
pkg_add python3
if [ "$EPS_OS_DISTRO" != "alpine" ]; then
pkg_add python3-venv
fi
PYTHON_VERSION=$(python3 -V | sed 's/.* \([0-9]\).\([0-9]*\).*/\1.\2/')
if printf "$PYTHON_VERSION\n3.2" | sort -cV &>/dev/null; then
step_end "Python 3.2+ required, you currently have ${CLR_CYB}v$PYTHON_VERSION${CLR} installed" 1
fi
_pipGetScript="https://bootstrap.pypa.io/get-pip.py"
if printf "$PYTHON_VERSION\n3.7" | sort -cV &>/dev/null; then
_pipGetScript="https://bootstrap.pypa.io/pip/$PYTHON_VERSION/get-pip.py"
fi
# Setup venv and install pip packages in venv
python3 -m venv /opt/certbot/
. /opt/certbot/bin/activate
os_fetch -O- $_pipGetScript | python3 >$__OUTPUT
pip install -q -U --no-cache-dir cryptography cffi certbot tldextract
PIP_VERSION=$(pip -V 2>&1 | grep -o 'pip [0-9.]* ' | awk '{print $2}')
deactivate
ln -sf /usr/bin/python3 /usr/bin/python
ln -sf /opt/certbot/bin/pip /usr/bin/pip
ln -sf /opt/certbot/bin/certbot /usr/bin/certbot
step_end "Python ${CLR_CYB}v$PYTHON_VERSION${CLR} ${CLR_GN}and Pip${CLR} ${CLR_CYB}v$PIP_VERSION${CLR} ${CLR_GN}Installed"
step_start "Openresty"
if [ "$EPS_OS_DISTRO" = "alpine" ]; then
os_fetch -O /etc/apk/keys/admin@openresty.com-5ea678a6.rsa.pub 'http://openresty.org/package/admin@openresty.com-5ea678a6.rsa.pub'
sed -i '/openresty.org/d' /etc/apk/repositories >$__OUTPUT
printf "http://openresty.org/package/alpine/v$EPS_OS_VERSION/main"| tee -a /etc/apk/repositories >$__OUTPUT
else
os_fetch -O- https://openresty.org/package/pubkey.gpg | gpg --yes --dearmor -o /usr/share/keyrings/openresty.gpg &>$__OUTPUT
repository=http://openresty.org/package/$EPS_OS_DISTRO
if [ "$EPS_OS_ARCH" != "amd64" ]; then
repository=http://openresty.org/package/$EPS_OS_ARCH/$EPS_OS_DISTRO
fi
source="deb [arch=$EPS_OS_ARCH signed-by=/usr/share/keyrings/openresty.gpg] $repository $EPS_OS_CODENAME "
if [ "$EPS_OS_DISTRO" = "debian" ]; then
source+="openresty"
else
source+="main"
fi
printf "$source" | tee /etc/apt/sources.list.d/openresty.list >$__OUTPUT
fi
pkg_update
pkg_add openresty
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
ln -sf /usr/local/openresty/nginx/ /etc/nginx
OPENRESTY_VERSION=$(openresty -v 2>&1 | grep -o '[0-9.]*$')
step_end "Openresty ${CLR_CYB}v$OPENRESTY_VERSION${CLR} ${CLR_GN}Installed"
step_start "Node.js"
_nodePackage=""
_nodeArch=""
_opensslArch="linux*"
case "${EPS_OS_ARCH##*-}" in
amd64 | x86_64) _nodeArch="x64" _opensslArch="linux-x86_64";;
ppc64el) _nodeArch="ppc64le" _opensslArch="linux-ppc64le";;
s390x) _nodeArch="s390x" _opensslArch="linux-s390x";;
arm64 | aarch64) _nodeArch="arm64" _opensslArch="linux-aarch64";;
armhf) _nodeArch="armv7l" _opensslArch="linux-armv4";;
i386 | x86) _nodeArch="x86" _opensslArch="linux-elf";;
*) step_end "Architecture not supported: ${CLR_CYB}$EPS_OS_ARCH${CLR}" 1;;
esac
if [ "$EPS_OS_DISTRO" = "alpine" ]; then
if [ "$_nodeArch" != "x64" ]; then
step_end "Architecture not supported: ${CLR_CYB}$EPS_OS_ARCH${CLR}" 1
fi
_nodePackage="node-$NODE_VERSION-linux-$_nodeArch-musl.tar.xz"
os_fetch -O $_nodePackage https://unofficial-builds.nodejs.org/download/release/$NODE_VERSION/$_nodePackage
os_fetch -O SHASUMS256.txt https://unofficial-builds.nodejs.org/download/release/$NODE_VERSION/SHASUMS256.txt
else
_nodePackage="node-$NODE_VERSION-linux-$_nodeArch.tar.xz"
os_fetch -O $_nodePackage https://nodejs.org/dist/$NODE_VERSION/$_nodePackage
os_fetch -O SHASUMS256.txt https://nodejs.org/dist/$NODE_VERSION/SHASUMS256.txt
fi
grep " $_nodePackage\$" SHASUMS256.txt | sha256sum -c >$__OUTPUT
tar -xJf "$_nodePackage" -C /usr/local --strip-components=1 --no-same-owner >$__OUTPUT
ln -sf /usr/local/bin/node /usr/local/bin/nodejs
rm "$_nodePackage" SHASUMS256.txt
find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name "$_opensslArch" -exec rm -rf {} \; >$__OUTPUT
step_end "Node.js ${CLR_CYB}$NODE_VERSION${CLR} ${CLR_GN}Installed"
step_start "Yarn"
export GNUPGHOME="$(mktemp -d)"
for key in 6A010C5166006599AA17F08146C2130DFD2497F5; do
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ;
done
os_fetch -O yarn-v$YARN_VERSION.tar.gz https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz
os_fetch -O yarn-v$YARN_VERSION.tar.gz.asc https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc
gpg -q --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz >$__OUTPUT
gpgconf --kill all
tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/
ln -sf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn
ln -sf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg
rm -rf "$GNUPGHOME" yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz
step_end "Yarn ${CLR_CYB}v$YARN_VERSION${CLR} ${CLR_GN}Installed"
step_start "Nginx Proxy Manager" "Downloading" "Downloaded"
NPM_VERSION=$(os_fetch -O- https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
os_fetch -O- https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v$NPM_VERSION | tar -xz
cd ./nginx-proxy-manager-$NPM_VERSION
step_end "Nginx Proxy Manager ${CLR_CYB}v$NPM_VERSION${CLR} ${CLR_GN}Downloaded"
step_start "Enviroment" "Setting up" "Setup"
# Update NPM version in package.json files
sed -i "s+0.0.0+$NPM_VERSION+g" backend/package.json
sed -i "s+0.0.0+$NPM_VERSION+g" frontend/package.json
# Fix nginx config files for use with openresty defaults
sed -i 's/user npm/user root/g; s/^pid/#pid/g; s+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf
sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg
_nginxConfigs=$(find ./ -type f -name "*.conf")
for _nginxConfig in $_nginxConfigs; do
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$_nginxConfig"
done
# Copy runtime files
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
# Create required folders
mkdir -p \
/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 \
/data/letsencrypt-acme-challenge \
/run/nginx \
/tmp/nginx/body \
/var/log/nginx \
/var/lib/nginx/cache/public \
/var/lib/nginx/cache/private \
/var/cache/nginx/proxy_temp
# Set permissions
touch /var/log/nginx/error.log
chmod 777 /var/log/nginx/error.log
chmod -R 777 /var/cache/nginx
chmod 644 /etc/logrotate.d/nginx-proxy-manager
chown root /tmp/nginx
chmod -R 777 /var/cache/nginx
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf) valid=10s;" > /etc/nginx/conf.d/include/resolvers.conf
# Copy app files
mkdir -p /app/global /app/frontend/images
cp -r backend/* /app
cp -r global/* /app/global
step_start "Frontend" "Building" "Built"
cd ./frontend
export NODE_ENV=development
yarn cache clean --silent --force >$__OUTPUT
yarn install --silent --network-timeout=30000 >$__OUTPUT
yarn build >$__OUTPUT
cp -r dist/* /app/frontend
cp -r app-images/* /app/frontend/images
step_start "Backend" "Initializing" "Initialized"
rm -rf /app/config/default.json &>$__OUTPUT
if [ ! -f /app/config/production.json ]; then
_npmConfig="{\n \"database\": {\n \"engine\": \"knex-native\",\n \"knex\": {\n \"client\": \"sqlite3\",\n \"connection\": {\n \"filename\": \"/data/database.sqlite\"\n }\n }\n }\n}"
printf "$_npmConfig\n" | tee /app/config/production.json >$__OUTPUT
fi
cd /app
export NODE_ENV=development
yarn install --silent --network-timeout=30000 >$__OUTPUT
step_start "Services" "Starting" "Started"
printf "$EPS_SERVICE_DATA\n" | tee $EPS_SERVICE_FILE >$__OUTPUT
chmod a+x $EPS_SERVICE_FILE
svc_add openresty
svc_add npm
step_start "Enviroment" "Cleaning" "Cleaned"
yarn cache clean --silent --force >$__OUTPUT
# find /tmp -mindepth 1 -maxdepth 1 -not -name nginx -exec rm -rf '{}' \;
if [ "$EPS_CLEANUP" = true ]; then
pkg_del "$EPS_DEPENDENCIES"
fi
pkg_clean
step_end "Installation complete"
printf "\nNginx Proxy Manager should be reachable at ${CLR_CYB}http://$(os_ip):81${CLR}\n\n"

193
create.sh Normal file
View File

@@ -0,0 +1,193 @@
#!/usr/bin/env bash
export EPS_BASE_URL=https://raw.githubusercontent.com/ej52/proxmox-scripts/main
export EPS_CT_INSTALL=true
export EPS_UTILS=$(wget --no-cache -qO- $EPS_BASE_URL/utils/common.sh)
source <(echo -n "$EPS_UTILS")
pms_bootstrap
pms_settraps
while [ "$#" -gt 0 ]; do
case $1 in
--app)
EPS_APP_NAME=$2
shift;;
--id)
EPS_CT_ID=$2
shift;;
--os)
EPS_OS_DISTRO=$2;
shift;;
--os-version)
EPS_OS_VERSION=$2;
shift;;
--bridge)
EPS_CT_NETWORK_BRIDGE=$2
shift;;
--cores)
EPS_CT_CPU_CORES=$2
shift;;
--disksize)
EPS_CT_DISK_SIZE=$2
shift;;
--hostname)
EPS_CT_HOSTNAME=$2
shift;;
--memory)
EPS_CT_MEMORY=$2
shift;;
--storage)
EPS_CT_STORAGE_CONTAINER=$2
shift;;
--templates)
EPS_CT_STORAGE_TEMPLATES=$2
shift;;
--swap)
EPS_CT_SWAP=$2
shift;;
--cleanup)
EPS_CLEANUP=true;;
*)
log "error" "Unrecognized option: ${CLR_CYB}$1${CLR}" "" 1;;
esac
shift
done
EPS_APP_NAME=${EPS_APP_NAME:-nginx-proxy-manager}
if [ -z "$EPS_APP_NAME" ]; then
log "error" "No application provided" "" 1
fi
export EPS_APP_CONFIG=$(wget --no-cache -qO- $EPS_BASE_URL/apps/$EPS_APP_NAME/config.sh)
if [ $? -gt 0 ]; then
log "error" "Application config not found for ${CLR_CYB}$EPS_APP_NAME${CLR}" "" 1
fi
EPS_APP_INSTALL=$(wget --no-cache -qO- $EPS_BASE_URL/apps/$EPS_APP_NAME/install.sh)
if [ $? -gt 0 ]; then
log "error" "No install script found for ${CLR_CYB}$EPS_APP_NAME${CLR}" "" 1
fi
EPS_CT_ID=${EPS_CT_ID:-$(pvesh get /cluster/nextid)}
EPS_CT_HOSTNAME=${EPS_CT_HOSTNAME:-${EPS_APP_NAME}}
EPS_CT_NETWORK_BRIDGE=${EPS_CT_NETWORK_BRIDGE:-vmbr0}
EPS_CT_STORAGE_CONTAINER=${EPS_CT_STORAGE_CONTAINER:-local-lvm}
EPS_CT_STORAGE_TEMPLATES=${EPS_CT_STORAGE_TEMPLATES:-local}
export EPS_OS_DISTRO=${EPS_OS_DISTRO:-alpine}
EPS_OS_VERSION=${EPS_OS_VERSION:-}
export EPS_CLEANUP=${EPS_CLEANUP:-false}
EPS_CT_CPU_CORES=${EPS_CT_CPU_CORES:-1}
EPS_CT_DISK_SIZE=${EPS_CT_DISK_SIZE:-4}
EPS_CT_MEMORY=${EPS_CT_MEMORY:-512}
EPS_CT_SWAP=${EPS_CT_SWAP:-0}
[ "$EPS_CT_ID" -ge 100 ] || log "error" "ID cannot be less than 100" "" 1
if pct status $EPS_CT_ID &>$__OUTPUT; then
log "error" "ID is already in use: ${CLR_CYB}$EPS_CT_ID${CLR}" "" 1
fi
source <(echo -n "$EPS_APP_CONFIG")
pms_header
EPS_OS_NAME=$(os_name)
pms_check_os
[ "$EPS_CT_DISK_SIZE" -ge 0 ] 2>$__OUTPUT || log "error" "Disk Size should be a vaild integer" "" 1
lxc_checks
log "info" "Container will be created using the following settings.
Application: ${CLR_CYB}$EPS_APP_NAME${CLR_CY}
OS Distribution: ${CLR_CYB}$EPS_OS_DISTRO${CLR_CY}
OS Version: ${CLR_CYB}${EPS_OS_VERSION:-latest}${CLR_CY}
Container ID: ${CLR_CYB}$EPS_CT_ID${CLR_CY}
Container Hostname: ${CLR_CYB}$EPS_CT_HOSTNAME${CLR_CY}
Allocated Cores: ${CLR_CYB}$EPS_CT_CPU_CORES${CLR_CY}
Allocated Memory: ${CLR_CYB}$EPS_CT_MEMORY${CLR_CY}
Allocated Swap: ${CLR_CYB}$EPS_CT_SWAP${CLR_CY}
Allocated Disk Size: ${CLR_CYB}$EPS_CT_DISK_SIZE${CLR_CY}
Network Bridge: ${CLR_CYB}$EPS_CT_NETWORK_BRIDGE${CLR_CY}
Container Storage: ${CLR_CYB}$EPS_CT_STORAGE_CONTAINER${CLR_CY}
Template Storage: ${CLR_CYB}$EPS_CT_STORAGE_TEMPLATES${CLR_CY}
Script Cleanup: ${CLR_CYB}$EPS_CLEANUP${CLR_CY}
${CLR_YLB}If you want to abort, hit ctrl+c within 10 seconds...${CLR}"
sleep 10
pms_header
step_start "LXC templates" "Checking" "OK"
_template=""
_templates_downloaded=($(pveam list $EPS_CT_STORAGE_TEMPLATES | grep -Eo "$EPS_OS_DISTRO.*\.(gz|xz|zst)" || true))
if [ ${#_templates_downloaded[@]} -gt 0 ]; then
for t in ${_templates_downloaded[*]}; do
if [ "${t%\-*}" = "$EPS_OS_DISTRO-$EPS_OS_VERSION" ]; then
_template=$t
break;
fi
done
fi
if [ -z $_template ]; then
pveam update &>$__OUTPUT
_templates_available=($(pveam available -section system | grep -Eo "$EPS_OS_DISTRO.*\.(gz|xz|zst)" | sort -r -t - -k 2 -V))
if [ ${#_templates_available[@]} -gt 0 ]; then
if [ -z $EPS_OS_VERSION ]; then
_template=${_templates_available[0]}
else
for t in ${_templates_available[*]}; do
if [ "${t%\-*}" = "$EPS_OS_DISTRO-$EPS_OS_VERSION" ]; then
_template=$t
break;
fi
done
fi
if [[ ! "${_templates_downloaded[*]}" =~ "$_template" ]]; then
log "info" "Downloading LXC template: ${CLR_CYB}$_template${CLR}" $(__clr)
sleep 3
pveam download $EPS_CT_STORAGE_TEMPLATES $_template >$__OUTPUT
fi
fi
else
sleep 3
fi
if [ -z $_template ]; then
step_end "LXC template not found for: ${CLR_CYB}${EPS_OS_DISTRO}:${EPS_OS_VERSION:-latest}${CLR}" 1
fi
step_end "Using LXC template: ${CLR_CYB}${_template}${CLR}"
step_start "LXC container" "Creating" "Created"
_storage_type=$(pvesm status -storage $EPS_CT_STORAGE_CONTAINER >$__OUTPUT | awk 'NR>1 {print $2}')
if [ "$_storage_type" = "zfspool" ]; then
log "warn" "Some containers may not work properly due to ZFS not supporting 'fallocate'."
sleep 3
fi
_pct_options=(
-arch $(dpkg --print-architecture)
-cmode shell
-hostname $EPS_CT_HOSTNAME
-cores $EPS_CT_CPU_CORES
-memory $EPS_CT_MEMORY
-net0 name=eth0,bridge=$EPS_CT_NETWORK_BRIDGE,ip=dhcp
-onboot 1
-ostype $EPS_OS_DISTRO
-rootfs $EPS_CT_STORAGE_CONTAINER:${EPS_CT_DISK_SIZE:-4}
-swap $EPS_CT_SWAP
-tags $EPS_APP_NAME
)
pct create $EPS_CT_ID "$EPS_CT_STORAGE_TEMPLATES:vztmpl/$_template" ${_pct_options[@]} >$__OUTPUT
pct start $EPS_CT_ID
sleep 2
if [ "$EPS_OS_DISTRO" = "alpine" ]; then
pct exec "$EPS_CT_ID" -- ash -c "apk add bash >/dev/null"
fi
step_end "LXC container ${CLR_CYB}$EPS_CT_ID${CLR_GN} created successfully"
trap - ERR
lxc-attach -n $EPS_CT_ID -- bash -c "$EPS_APP_INSTALL"

52
install.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env sh
export EPS_BASE_URL=https://raw.githubusercontent.com/ej52/proxmox-scripts/main
export EPS_CT_INSTALL=false
export EPS_UTILS=$(wget --no-cache -qO- $EPS_BASE_URL/utils/common.sh)
source <(echo -n "$EPS_UTILS")
while [ "$#" -gt 0 ]; do
case $1 in
--app)
EPS_APP_NAME="$2"
shift;;
--cleanup)
EPS_CLEANUP=true
;;
*)
log "error" "Unrecognized option: ${CLR_CYB}$1${CLR}" "" 1;;
esac
shift
done
EPS_APP_NAME=${EPS_APP_NAME:-}
export EPS_CLEANUP=${EPS_CLEANUP:-false}
if [ -z "$EPS_APP_NAME" ]; then
log "error" "No application provided" "" 1
fi
export EPS_APP_CONFIG=$(wget --no-cache -qO- $EPS_BASE_URL/apps/$EPS_APP_NAME/config.sh)
if [ $? -gt 0 ]; then
log "error" "No config found for ${CLR_CYB}$EPS_APP_NAME${CLR}" "" 1
fi
EPS_APP_INSTALL=$(wget --no-cache -qO- $EPS_BASE_URL/apps/$EPS_APP_NAME/install.sh)
if [ $? -gt 0 ]; then
log "error" "No install script found for ${CLR_CYB}$EPS_APP_NAME${CLR}" "" 1
fi
EPS_OS_NAME=$(os_name)
export EPS_OS_DISTRO=$(os_distro)
source <(echo -n "$EPS_APP_CONFIG")
pms_header
pms_check_os
if [ "$EPS_OS_DISTRO" = "alpine" ]; then
[ "$(command -v bash)" ] || apk add bash >/dev/null
fi
trap - ERR
bash -c "$EPS_APP_INSTALL"

View File

@@ -1,52 +0,0 @@
# Nginx Proxy Manager in Proxmox LXC container
Many benefits can be gained by using a LXC container compared to a VM. The resources needed to run a LXC container are less than running a VM. Modifing the resouces assigned to the LXC container can be done without having to reboot the container. The serial devices connected to Proxmox can be shared with multiple LXC containers simulatenously.
## Usage
To create a new LXC container on Proxmox and setup Nginx Proxy Manager to run inside of it, run the following in a SSH connection or the Proxmox web shell.
***Note:*** _tested with proxmox 6.4+_
***Note:*** _This will create alpine container_
```bash
curl -sL https://raw.githubusercontent.com/ej52/proxmox/main/lxc/nginx-proxy-manager/create.sh | bash -s
```
### Command line arguments
| argument | default | description |
|--------------------|----------------------|--------------------------------------------------------|
| --id | $nextid | container id |
| --bridge | vmbr0 | bridge used for eth0 |
| --cores | 1 | number of cpu cores |
| --disksize | 2G | size of disk |
| --hostname | nginx-proxy-manager | hostname of the container |
| --memory | 512 | amount of memory |
| --storage | local-lvm | storage location for container disk |
| --templates | local | storage location for templates |
| --swap | 0 | amount of SWAP |
you can set these parameters by appending ` -- <parameter> <value>` like:
```bash
curl -sL https://raw.githubusercontent.com/ej52/proxmox/main/lxc/nginx-proxy-manager/create.sh | bash -s -- --cores 4
```
### Console
There is no login required to access the console from the Proxmox web UI. If you are presented with a blank screen, press `CTRL + C` to generate a prompt.
## Alternative Usage
If you are not using proxmox or want to install this on a existing Alpine box, you can run the setup script itself.
***Note:*** _Only Alpine, Debian and Ubuntu are currently supported by this script_
```bash
wget --no-cache -qO - https://raw.githubusercontent.com/ej52/proxmox/main/lxc/nginx-proxy-manager/setup.sh | sh
```
## Thanks
- [whiskerz007](https://github.com/whiskerz007?tab=repositories)

View File

@@ -1,195 +0,0 @@
#!/usr/bin/env bash
set -Eeuo pipefail
trap error ERR
trap 'popd >/dev/null; rm -rf $_temp_dir;' EXIT
function info { echo -e "\e[32m[info] $*\e[39m"; }
function warn { echo -e "\e[33m[warn] $*\e[39m"; }
function error {
trap - ERR
if [ -z "${1-}" ]; then
echo -e "\e[31m[error] $(caller): ${BASH_COMMAND}\e[39m"
else
echo -e "\e[31m[error] $1\e[39m"
fi
if [ ! -z ${_ctid-} ]; then
if $(pct status $_ctid &>/dev/null); then
if [ "$(pct status $_ctid 2>/dev/null | awk '{print $2}')" == "running" ]; then
pct stop $_ctid &>/dev/null
fi
pct destroy $_ctid &>/dev/null
elif [ "$(pvesm list $_storage --vmid $_ctid 2>/dev/null | awk 'FNR == 2 {print $2}')" != "" ]; then
pvesm free $_rootfs &>/dev/null
fi
fi
exit 1
}
# Base raw github URL
_raw_base="https://raw.githubusercontent.com/ej52/proxmox-scripts/main/lxc/nginx-proxy-manager"
# Operating system
_os_type=alpine
_os_version=3.16
# System architecture
_arch=$(dpkg --print-architecture)
# Create temp working directory
_temp_dir=$(mktemp -d)
pushd $_temp_dir >/dev/null
# Parse command line parameters
while [[ $# -gt 0 ]]; do
arg="$1"
case $arg in
--id)
_ctid=$2
shift
;;
--bridge)
_bridge=$2
shift
;;
--cores)
_cpu_cores=$2
shift
;;
--disksize)
_disk_size=$2
shift
;;
--hostname)
_host_name=$2
shift
;;
--memory)
_memory=$2
shift
;;
--storage)
_storage=$2
shift
;;
--templates)
_storage_template=$2
shift
;;
--swap)
_swap=$2
shift
;;
*)
error "Unrecognized option $1"
;;
esac
shift
done
# Check user settings or set defaults
_ctid=${_ctid:-`pvesh get /cluster/nextid`}
_cpu_cores=${_cpu_cores:-1}
_disk_size=${_disk_size:-2G}
_host_name=${_host_name:-nginx-proxy-manager}
_bridge=${_bridge:-vmbr0}
_memory=${_memory:-512}
_swap=${_swap:-0}
_storage=${_storage:-local-lvm}
_storage_template=${_storage_template:-local}
# Test if ID is in use
if pct status $_ctid &>/dev/null; then
warn "ID '$_ctid' is already in use."
unset _ctid
error "Cannot use ID that is already in use."
fi
echo ""
warn "Container will be created using the following settings."
warn ""
warn "ctid: $_ctid"
warn "hostname: $_host_name"
warn "cores: $_cpu_cores"
warn "memory: $_memory"
warn "swap: $_swap"
warn "disksize: $_disk_size"
warn "bridge: $_bridge"
warn "storage: $_storage"
warn "templates: $_storage_template"
warn ""
warn "If you want to abort, hit ctrl+c within 10 seconds..."
echo ""
sleep 10
# Download latest Alpine LXC template
info "Updating LXC template list..."
pveam update &>/dev/null
info "Downloading LXC template..."
mapfile -t _templates < <(pveam available -section system | sed -n "s/.*\($_os_type-$_os_version.*\)/\1/p" | sort -t - -k 2 -V)
[ ${#_templates[@]} -eq 0 ] \
&& error "No LXC template found for $_os_type-$_os_version"
_template="${_templates[-1]}"
pveam download $_storage_template $_template &>/dev/null \
|| error "A problem occured while downloading the LXC template."
# Create variables for container disk
_storage_type=$(pvesm status -storage $_storage 2>/dev/null | awk 'NR>1 {print $2}')
case $_storage_type in
btrfs|dir|nfs)
_disk_ext=".raw"
_disk_ref="$_ctid/"
;;
zfspool)
_disk_prefix="subvol"
_disk_format="subvol"
;;
esac
_disk=${_disk_prefix:-vm}-${_ctid}-disk-0${_disk_ext-}
_rootfs=${_storage}:${_disk_ref-}${_disk}
# Create LXC
info "Allocating storage for LXC container..."
pvesm alloc $_storage $_ctid $_disk $_disk_size --format ${_disk_format:-raw} &>/dev/null \
|| error "A problem occured while allocating storage."
if [ "$_storage_type" = "zfspool" ]; then
warn "Some containers may not work properly due to ZFS not supporting 'fallocate'."
else
mkfs.ext4 $(pvesm path $_rootfs) &>/dev/null
fi
info "Creating LXC container..."
_pct_options=(
-arch $_arch
-cmode shell
-hostname $_host_name
-cores $_cpu_cores
-memory $_memory
-net0 name=eth0,bridge=$_bridge,ip=dhcp
-onboot 1
-ostype $_os_type
-rootfs $_rootfs,size=$_disk_size
-storage $_storage
-swap $_swap
-tags npm
)
pct create $_ctid "$_storage_template:vztmpl/$_template" ${_pct_options[@]} &>/dev/null \
|| error "A problem occured while creating LXC container."
# Set container timezone to match host
cat << 'EOF' >> /etc/pve/lxc/${_ctid}.conf
lxc.hook.mount: sh -c 'ln -fs $(readlink /etc/localtime) ${LXC_ROOTFS_MOUNT}/etc/localtime'
EOF
# Setup container
info "Setting up LXC container..."
pct start $_ctid
sleep 3
pct exec $_ctid -- sh -c "wget --no-cache -qO - $_raw_base/setup.sh | sh"

View File

@@ -1,259 +0,0 @@
#!/usr/bin/env sh
set -euo pipefail
trap trapexit EXIT SIGTERM
TEMPDIR=$(mktemp -d)
TEMPLOG="$TEMPDIR/tmplog"
TEMPERR="$TEMPDIR/tmperr"
LASTCMD=""
WGETOPT="-t 1 -T 15 -q"
DEVDEPS="npm g++ make gcc git python3-dev musl-dev libffi-dev openssl-dev"
NPMURL="https://github.com/NginxProxyManager/nginx-proxy-manager"
cd $TEMPDIR
touch $TEMPLOG
# Helpers
log() {
logs=$(cat $TEMPLOG | sed -e "s/34/32/g" | sed -e "s/info/success/g");
clear && printf "\033c\e[3J$logs\n\e[34m[info] $*\e[0m\n" | tee $TEMPLOG;
}
runcmd() {
LASTCMD=$(grep -n "$*" "$0" | sed "s/[[:blank:]]*runcmd//");
if [[ "$#" -eq 1 ]]; then
eval "$@" 2>$TEMPERR;
else
$@ 2>$TEMPERR;
fi
}
trapexit() {
status=$?
if [[ $status -eq 0 ]]; then
logs=$(cat $TEMPLOG | sed -e "s/34/32/g" | sed -e "s/info/success/g")
clear && printf "\033c\e[3J$logs\n";
elif [[ -s $TEMPERR ]]; then
logs=$(cat $TEMPLOG | sed -e "s/34/31/g" | sed -e "s/info/error/g")
err=$(cat $TEMPERR | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g' | rev | cut -d':' -f1 | rev | cut -d' ' -f2-)
clear && printf "\033c\e[3J$logs\e[33m\n$0: line $LASTCMD\n\e[33;2;3m$err\e[0m\n"
else
printf "\e[33muncaught error occurred\n\e[0m"
fi
# Cleanup
rm -rf $TEMPDIR
apk del $DEVDEPS &>/dev/null
}
# Check for previous install
if [ -f /etc/init.d/npm ]; then
log "Stopping services"
rc-service npm stop &>/dev/null
rc-service openresty stop &>/dev/null
sleep 2
log "Cleaning old files"
# Cleanup for new install
rm -rf /app \
/var/www/html \
/etc/nginx \
/var/log/nginx \
/var/lib/nginx \
/var/cache/nginx &>/dev/null
log "Removing old dependencies"
apk del certbot $DEVDEPS &>/dev/null
fi
log "Checking for latest openresty repository"
. /etc/os-release
_alpine_version=${VERSION_ID%.*}
# add openresty public key
if [ ! -f /etc/apk/keys/admin@openresty.com-5ea678a6.rsa.pub ]; then
runcmd 'wget $WGETOPT -P /etc/apk/keys/ http://openresty.org/package/admin@openresty.com-5ea678a6.rsa.pub'
fi
# Get the latest openresty repository
_repository_version=$(wget $WGETOPT "http://openresty.org/package/alpine/" -O - | grep -Eo "[0-9]{1}\.[0-9]{1,2}" | sort -uVr | head -n1)
_repository_version=$(printf "$_repository_version\n$_alpine_version" | sort -V | head -n1)
_repository="http://openresty.org/package/alpine/v$_repository_version/main"
# Update/Insert openresty repository
grep -q 'openresty.org' /etc/apk/repositories &&
sed -i "/openresty.org/c\\$_repository/" /etc/apk/repositories || echo $_repository >> /etc/apk/repositories
# Update container OS
log "Updating container OS"
echo "fs.file-max = 65535" > /etc/sysctl.conf
runcmd apk update
runcmd apk upgrade
# Install dependancies
log "Installing dependencies"
runcmd 'apk add python3 openresty nodejs yarn openssl apache2-utils logrotate $DEVDEPS'
# Setup python env and PIP
log "Setting up python"
python3 -m venv /opt/certbot/
runcmd python3 -m ensurepip --upgrade
# Install certbot and python dependancies
runcmd pip3 install --no-cache-dir -U cryptography==3.3.2
runcmd pip3 install --no-cache-dir cffi certbot
log "Checking for latest NPM release"
# Get latest version information for nginx-proxy-manager
runcmd 'wget $WGETOPT -O ./_latest_release $NPMURL/releases/latest'
_latest_version=$(basename $(cat ./_latest_release | grep -wo "expanded_assets/v.*\d") | cut -d'v' -f2)
# Download nginx-proxy-manager source
log "Downloading NPM v$_latest_version"
runcmd 'wget $WGETOPT -c $NPMURL/archive/v$_latest_version.tar.gz -O - | tar -xz'
cd ./nginx-proxy-manager-$_latest_version
log "Setting up enviroment"
# Crate required symbolic links
ln -sf /usr/bin/python3 /usr/bin/python
ln -sf /usr/bin/pip3 /usr/bin/pip
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
# Update NPM version in package.json files
sed -i "s+0.0.0+$_latest_version+g" backend/package.json
sed -i "s+0.0.0+$_latest_version+g" frontend/package.json
# Fix nginx config files for use with openresty defaults
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
# Copy runtime files
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
# Create required folders
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
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
# thanks @tfmm
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" > /etc/nginx/conf.d/include/resolvers.conf
# Generate dummy self-signed certificate.
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
log "Generating dummy SSL certificate"
runcmd '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'
fi
# Copy app files
mkdir -p /app/global /app/frontend/images
cp -r backend/* /app
cp -r global/* /app/global
# Build the frontend
log "Building frontend"
cd ./frontend
export NODE_ENV=development
runcmd yarn install
runcmd yarn build
cp -r dist/* /app/frontend
cp -r app-images/* /app/frontend/images
# Initialize backend
log "Initializing backend"
rm -rf /app/config/default.json &>/dev/null
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
export NODE_ENV=development
runcmd yarn install
# Create NPM service
log "Creating NPM service"
cat << 'EOF' > /etc/init.d/npm
#!/sbin/openrc-run
description="Nginx Proxy Manager"
command="/usr/bin/node"
command_args="index.js --abort_on_uncaught_exception --max_old_space_size=250"
command_background="yes"
directory="/app"
pidfile="/var/run/npm.pid"
output_log="/var/log/npm.log"
error_log="/var/log/npm.err"
depends () {
before openresty
}
start_pre() {
mkdir -p /tmp/nginx/body \
/data/letsencrypt-acme-challenge
export NODE_ENV=production
}
stop() {
pkill -9 -f node
return 0
}
restart() {
$0 stop
$0 start
}
EOF
chmod a+x /etc/init.d/npm
rc-update add npm boot &>/dev/null
rc-update add openresty boot &>/dev/null
rc-service openresty stop &>/dev/null
# Start services
log "Starting services"
runcmd rc-service openresty start
runcmd rc-service npm start
IP=$(ip a s dev eth0 | sed -n '/inet / s/\// /p' | awk '{print $2}')
log "Installation complete
\e[0mNginx Proxy Manager should be reachable at the following URL.
http://${IP}:81
"

View File

@@ -1,244 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
trap trapexit EXIT SIGTERM
DISTRO_ID=$(cat /etc/*-release | grep -w ID | cut -d= -f2 | tr -d '"')
DISTRO_CODENAME=$(cat /etc/*-release | grep -w VERSION_CODENAME | cut -d= -f2 | tr -d '"')
TEMPDIR=$(mktemp -d)
TEMPLOG="$TEMPDIR/tmplog"
TEMPERR="$TEMPDIR/tmperr"
LASTCMD=""
WGETOPT="-t 1 -T 15 -q"
DEVDEPS="git build-essential libffi-dev libssl-dev python3-dev"
NPMURL="https://github.com/NginxProxyManager/nginx-proxy-manager"
cd $TEMPDIR
touch $TEMPLOG
# Helpers
log() {
logs=$(cat $TEMPLOG | sed -e "s/34/32/g" | sed -e "s/info/success/g");
clear && printf "\033c\e[3J$logs\n\e[34m[info] $*\e[0m\n" | tee $TEMPLOG;
}
runcmd() {
LASTCMD=$(grep -n "$*" "$0" | sed "s/[[:blank:]]*runcmd//");
if [[ "$#" -eq 1 ]]; then
eval "$@" 2>$TEMPERR;
else
$@ 2>$TEMPERR;
fi
}
trapexit() {
status=$?
if [[ $status -eq 0 ]]; then
logs=$(cat $TEMPLOG | sed -e "s/34/32/g" | sed -e "s/info/success/g")
clear && printf "\033c\e[3J$logs\n";
elif [[ -s $TEMPERR ]]; then
logs=$(cat $TEMPLOG | sed -e "s/34/31/g" | sed -e "s/info/error/g")
err=$(cat $TEMPERR | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g' | rev | cut -d':' -f1 | rev | cut -d' ' -f2-)
clear && printf "\033c\e[3J$logs\e[33m\n$0: line $LASTCMD\n\e[33;2;3m$err\e[0m\n"
else
printf "\e[33muncaught error occurred\n\e[0m"
fi
# Cleanup
apt-get remove --purge -y $DEVDEPS -qq &>/dev/null
apt-get autoremove -y -qq &>/dev/null
apt-get clean
rm -rf $TEMPDIR
rm -rf /root/.cache
}
# Check for previous install
if [ -f /lib/systemd/system/npm.service ]; then
log "Stopping services"
systemctl stop openresty
systemctl stop npm
# Cleanup for new install
log "Cleaning old files"
rm -rf /app \
/var/www/html \
/etc/nginx \
/var/log/nginx \
/var/lib/nginx \
/var/cache/nginx &>/dev/null
fi
# Install dependencies
log "Installing dependencies"
runcmd apt-get update
export DEBIAN_FRONTEND=noninteractive
runcmd 'apt-get install -y --no-install-recommends $DEVDEPS gnupg openssl ca-certificates apache2-utils logrotate'
# Install Python
log "Installing python"
runcmd apt-get install -y -q --no-install-recommends python3 python3-distutils python3-venv
python3 -m venv /opt/certbot/
export PATH=/opt/certbot/bin:$PATH
grep -qo "/opt/certbot" /etc/environment || echo "$PATH" > /etc/environment
# Install certbot and python dependancies
runcmd wget -qO - https://bootstrap.pypa.io/get-pip.py | python -
if [ "$(getconf LONG_BIT)" = "32" ]; then
runcmd pip install --no-cache-dir -U cryptography==3.3.2
fi
runcmd pip install --no-cache-dir cffi certbot
# Install openresty
log "Installing openresty"
wget -qO - https://openresty.org/package/pubkey.gpg | apt-key add -
_distro_release=$(wget $WGETOPT "http://openresty.org/package/$DISTRO_ID/dists/" -O - | grep -o "$DISTRO_CODENAME" | head -n1 || true)
if [ $DISTRO_ID = "ubuntu" ]; then
echo "deb [trusted=yes] http://openresty.org/package/$DISTRO_ID ${_distro_release:-focal} main" | tee /etc/apt/sources.list.d/openresty.list
else
echo "deb [trusted=yes] http://openresty.org/package/$DISTRO_ID ${_distro_release:-bullseye} openresty" | tee /etc/apt/sources.list.d/openresty.list
fi
runcmd apt-get update && apt-get install -y -q --no-install-recommends openresty
# Install nodejs
log "Installing nodejs"
runcmd wget -qO - https://deb.nodesource.com/setup_16.x | bash -
runcmd apt-get install -y -q --no-install-recommends nodejs
runcmd npm install --global yarn
# Get latest version information for nginx-proxy-manager
log "Checking for latest NPM release"
runcmd 'wget $WGETOPT -O ./_latest_release $NPMURL/releases/latest'
_latest_version=$(cat ./_latest_release | grep -Po '(?<=expanded_assets/v)[^"]+')
# Download nginx-proxy-manager source
log "Downloading NPM v$_latest_version"
runcmd 'wget $WGETOPT -c $NPMURL/archive/v$_latest_version.tar.gz -O - | tar -xz'
cd ./nginx-proxy-manager-$_latest_version
log "Setting up enviroment"
# Crate required symbolic links
ln -sf /usr/bin/python3 /usr/bin/python
ln -sf /opt/certbot/bin/pip /usr/bin/pip
ln -sf /opt/certbot/bin/certbot /usr/bin/certbot
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
ln -sf /usr/local/openresty/nginx/ /etc/nginx
# Update NPM version in package.json files
sed -i "s+0.0.0+$_latest_version+g" backend/package.json
sed -i "s+0.0.0+$_latest_version+g" frontend/package.json
# Fix nginx config files for use with openresty defaults
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
# Copy runtime files
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
# Create required folders
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
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
# thanks @tfmm
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" > /etc/nginx/conf.d/include/resolvers.conf
# Generate dummy self-signed certificate.
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
log "Generating dummy SSL certificate"
runcmd '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'
fi
# Copy app files
mkdir -p /app/global /app/frontend/images
cp -r backend/* /app
cp -r global/* /app/global
# Build the frontend
log "Building frontend"
cd ./frontend
export NODE_ENV=development
runcmd yarn install --network-timeout=30000
runcmd yarn build
cp -r dist/* /app/frontend
cp -r app-images/* /app/frontend/images
# Initialize backend
log "Initializing backend"
rm -rf /app/config/default.json &>/dev/null
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
export NODE_ENV=development
runcmd yarn install --network-timeout=30000
# Create NPM service
log "Creating NPM 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=-/bin/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
systemctl daemon-reload
systemctl enable npm
# Start services
log "Starting services"
runcmd systemctl start openresty
runcmd systemctl start npm
IP=$(hostname -I | cut -f1 -d ' ')
log "Installation complete
\e[0mNginx Proxy Manager should be reachable at the following URL.
http://${IP}:81
"

View File

@@ -1,32 +0,0 @@
#!/usr/bin/env sh
TMP=/tmp/npm_install.sh
URL=https://raw.githubusercontent.com/ej52/proxmox-scripts/main/lxc/nginx-proxy-manager/install
if [ "$(uname)" != "Linux" ]; then
echo "OS NOT SUPPORTED"
exit 1
fi
DISTRO=$(cat /etc/*-release | grep -w ID | cut -d= -f2 | tr -d '"')
if [ "$DISTRO" != "alpine" ] && [ "$DISTRO" != "ubuntu" ] && [ "$DISTRO" != "debian" ]; then
echo "DISTRO NOT SUPPORTED"
exit 1
fi
INSTALL_SCRIPT=$DISTRO
if [ "$DISTRO" = "ubuntu" ]; then
INSTALL_SCRIPT="debian"
fi
rm -rf $TMP
wget -O "$TMP" "$URL/$INSTALL_SCRIPT.sh"
chmod +x "$TMP"
if [ "$(command -v bash)" ]; then
$(command -v sudo) bash "$TMP"
else
sh "$TMP"
fi

48
utils/alpine.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
os_arch() {
printf $(apk --print-arch)
}
os_codename() {
printf $(os_version)
}
os_version() {
VERSION_ID=$(awk -F'=' '/^VERSION_ID=/{ print $NF }' /etc/os-release)
printf ${VERSION_ID%.*}
}
pkg_update() {
apk update -q >$__OUTPUT
}
pkg_upgrade() {
apk upgrade -q >$__OUTPUT
}
pkg_add() {
apk add -q -u $@ >$__OUTPUT
}
pkg_del() {
apk del -q --purge $@ >$__OUTPUT
}
pkg_clean() {
rm -rf /var/cache/apk/* >$__OUTPUT
}
svc_add() {
rc-update add $@ boot >$__OUTPUT
rc-service $@ stop &>$__OUTPUT
sleep 2
rc-service $@ start >$__OUTPUT
}
svc_start() {
rc-service $@ start >$__OUTPUT
}
svc_stop() {
rc-service $@ stop >$__OUTPUT
}

215
utils/common.sh Normal file
View File

@@ -0,0 +1,215 @@
# Color variables
CLR_RD="\033[0;31m"
CLR_RDB="\033[1;31m"
CLR_GN="\033[0;32m"
CLR_GNB="\033[1;32m"
CLR_YL="\033[0;33m"
CLR_YLB="\033[1;33m"
CLR_CY="\033[0;36m"
CLR_CYB="\033[1;36m"
CLR="\033[m"
# Helper variables
__OUTPUT=/dev/null
__SPIN_PID=0
__LAST_LINE=0
__STEP_NAME=""
__STEP_BUSY=""
__STEP_DONE=""
os_name() {
printf $(uname)
}
os_distro() {
printf $(awk -F'=' '/^ID=/{ print $NF }' /etc/os-release)
}
os_fetch() {
wget -t 3 -T 30 -q $@
}
os_ip() {
printf $(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)
}
pms_bootstrap() {
set -Eeuo pipefail
stty -echo
printf "\033[?25l"
if [ "$EPS_CT_INSTALL" = false ]; then
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >$__OUTPUT
fi
}
pms_header() {
log "info" "${EPS_APP_NAME:-Unknown}\n"
}
pms_check_os() {
local _os=${1:-$EPS_OS_NAME}
local _distro=${2:-$EPS_OS_DISTRO}
local _supported=false
if [ "$_os" != "Linux" ]; then
log "error" "OS not supported: ${CLR_CYB}$_os${CLR}" "" 1
fi
for d in $EPS_SUPPORTED_DISTROS; do
if [ "$d" = "$_distro" ]; then
_supported=true
break;
fi
done
if [ "$_supported" = false ]; then
log "error" "OS distribution not supported: ${CLR_CYB}$_distro${CLR}\n\n${CLR_YL}Supported distributions:${CLR} ${CLR_YLB}$EPS_SUPPORTED_DISTROS${CLR}" "" 1
fi
}
pms_settraps() {
trap '__trap_error ${BASH_LINENO:-"$LINENO"} ${FUNCNAME:-"$BASH_COMMAND"}' ERR
trap __trap_interrupt SIGHUP SIGINT SIGQUIT
trap __trap_exit EXIT
}
pms_cleartraps() {
trap - EXIT ERR SIGHUP SIGINT SIGQUIT
}
log () {
local type=${1:-"info"}
local message="$2"
local clear=${3:-}
local exit_code=${4:-0}
case $type in
info)
printf "${clear}${CLR_CYB} ${CLR_CY}${message}${CLR}\n";;
success)
printf "${clear}${CLR_GNB}${CLR_GN}${message}${CLR}\n";;
warn)
printf "${clear}${CLR_YLB}! ${CLR_YL}${message}${CLR}\n";;
error)
printf "${clear}${CLR_RDB}${CLR_RD}${message}${CLR}\n";;
*)
;;
esac
if [ $exit_code -gt 0 ]; then
exit $exit_code
fi
}
step_start() {
step_end
__STEP_NAME=${1:-}
__STEP_BUSY=${2:-${__STEP_BUSY}}
__STEP_DONE=${3:-${__STEP_DONE}}
__LAST_LINE=$(__row)
log "info" "${__STEP_BUSY} ${__STEP_NAME}"
__start_spinner &
__SPIN_PID=$!
disown
}
step_end() {
__stop_spinner
if [ -z "$__STEP_NAME" ]; then
return 0
fi
local message=${1:-}
local exit_code=${2:-0}
if [ -z "$message" ]; then
message="$__STEP_NAME $__STEP_DONE"
if [ "$exit_code" -gt 0 ]; then
message="$__STEP_NAME not $__STEP_DONE"
fi
fi
if [ "$exit_code" -gt 0 ]; then
log "error" "$message ${CLR_RD}" $(__clr)
exit $exit_code
else
log "success" "$message ${CLR_GN}" $(__clr)
fi
__STEP_NAME=""
__LAST_LINE=0
}
__start_spinner() {
local marks="⁘ ⁙"
while :; do
for mark in $marks; do
printf "$(__clr '1K')${CLR_CYB}$mark${CLR}\n"
sleep 0.35
done
done
}
__stop_spinner() {
if [ "$__SPIN_PID" -gt 0 ]; then
kill $__SPIN_PID &>$__OUTPUT
__SPIN_PID=0
fi
}
__row() {
local COL
local ROW
IFS=';' read -sdR -p $'\E[6n' ROW COL
printf "${ROW#*[}"
}
__clr() {
__LAST_LINE=${__LAST_LINE:-$(__row)}
local end=${1:-"0J"}
local row=${2:-$__LAST_LINE}
local col=${3:-1}
printf "\r\033[${row};${col}H\033[${end}"
}
__trap_exit() {
trap - ERR
__stop_spinner &>$__OUTPUT
if [ "$EPS_CT_INSTALL" = false ]; then
popd &>$__OUTPUT
rm -rf $TEMP_DIR &>$__OUTPUT
fi
printf "\033[?25h"
stty sane
}
__trap_interrupt() {
local exit_code="$?"
trap - ERR
stty sane
printf "\033[?25h"
[ -z "$__STEP_NAME" ] || log "warn" "$__STEP_NAME ${CLR_YL}not completely $__STEP_DONE${CLR}" $(__clr)
printf "\n${CLR_YLB}[TERMINATED]${CLR} process terminated with exit code ${CLR_YLB}$exit_code${CLR}\n"
}
__trap_error() {
local exit_code="$?"
local line_number="$1"
local command="$2"
local row=$(__row)
[ -z "$__STEP_NAME" ] || log "error" "$__STEP_NAME ${CLR_RD}not $__STEP_DONE" $(__clr 'K')
printf "$(__clr '' $row)\n${CLR_RDB}[ERROR]${CLR} on line ${CLR_RDB}$line_number${CLR} with exit code ${CLR_RDB}$exit_code${CLR} while executing command ${CLR_YLB}$command${CLR}\n"
}

48
utils/debian.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
os_arch() {
printf $(dpkg --print-architecture)
}
os_codename() {
printf $(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)
}
os_version() {
printf $(awk -F'=' '/^VERSION_ID=/{ print $NF }' /etc/os-release)
}
pkg_update() {
apt-get -y -qq update >$__OUTPUT
}
pkg_upgrade() {
apt-get -y -qq upgrade >$__OUTPUT
}
pkg_add() {
apt-get -y -qq --no-install-recommends install $@ >$__OUTPUT
}
pkg_del() {
apt-get -y -qq purge $@ >$__OUTPUT
}
pkg_clean() {
apt-get -y -qq autoremove >$__OUTPUT
apt-get clean >$__OUTPUT
}
svc_add() {
systemctl daemon-reload >$__OUTPUT
systemctl stop $@ &>$__OUTPUT
sleep 2
systemctl enable --now $@ >$__OUTPUT
}
svc_start() {
systemctl start $@ >$__OUTPUT
}
svc_stop() {
systemctl stop $@ >$__OUTPUT
}