Add NodeJS server as an alternative to PHP
This adds: - Two entries in the manifest: - A choice for the NodeJS version - A port (provisionned in any case due to ynh limitations, but this should not matter) - Services and configs: - Systemctl configs to run the NodeJS server - A watcher service and path to restart NodeJS upon file update - A custom NGinx config because it is incompatible with the default one - Docs: - More info in the description and admin The install/remove/backup/restore have been adapted and tested. The upgrade script is updated but not tested The change_url script does not change It is not possible to have both PHP and NodeJS to keep the scripts simple.
This commit is contained in:
parent
9defce59be
commit
9c6143df27
16 changed files with 261 additions and 4 deletions
14
conf/nginx-nodejs.conf
Normal file
14
conf/nginx-nodejs.conf
Normal file
|
@ -0,0 +1,14 @@
|
|||
#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent;
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:__PORT__/;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Scheme https;
|
||||
|
||||
proxy_buffering off;
|
||||
|
||||
# Include SSOWAT user panel.
|
||||
include conf.d/yunohost_panel.conf.inc;
|
||||
}
|
8
conf/nodejs-watcher.path
Normal file
8
conf/nodejs-watcher.path
Normal file
|
@ -0,0 +1,8 @@
|
|||
[Path]
|
||||
Unit=__APP__-nodejs-watcher.service
|
||||
|
||||
# Trigger on creation, deletion or change to a file
|
||||
PathChanged=__INSTALL_DIR__
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
12
conf/nodejs-watcher.service
Normal file
12
conf/nodejs-watcher.service
Normal file
|
@ -0,0 +1,12 @@
|
|||
[Unit]
|
||||
Description=__APP__ NodeJS restarter
|
||||
After=network.target
|
||||
StartLimitIntervalSec=10
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/bin/systemctl restart __APP__-nodejs.service
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
53
conf/nodejs.service
Normal file
53
conf/nodejs.service
Normal file
|
@ -0,0 +1,53 @@
|
|||
[Unit]
|
||||
Description=__APP__ NodeJS Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=__APP__
|
||||
Group=__APP__
|
||||
WorkingDirectory=__INSTALL_DIR__/www
|
||||
StandardOutput=append:/var/log/__APP__-nodejs.log
|
||||
StandardError=inherit
|
||||
Environment=__YNH_NODE_LOAD_PATH__
|
||||
Environment=PORT=__PORT__
|
||||
ExecStartPre=__YNH_NPM__ install
|
||||
ExecStartPre=__YNH_NPM__ run build
|
||||
ExecStart=__YNH_NPM__ run start
|
||||
|
||||
# Sandboxing options to harden security
|
||||
# Depending on specificities of your service/app, you may need to tweak these
|
||||
# .. but this should be a good baseline
|
||||
# Details for these options: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
NoNewPrivileges=yes
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
|
||||
RestrictNamespaces=yes
|
||||
RestrictRealtime=yes
|
||||
DevicePolicy=closed
|
||||
ProtectClock=yes
|
||||
ProtectHostname=yes
|
||||
ProtectProc=invisible
|
||||
ProtectSystem=full
|
||||
ProtectControlGroups=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelTunables=yes
|
||||
LockPersonality=yes
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap @cpu-emulation @privileged
|
||||
|
||||
# Denying access to capabilities that should not be relevant for webapps
|
||||
# Doc: https://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||
CapabilityBoundingSet=~CAP_RAWIO CAP_MKNOD
|
||||
CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
|
||||
CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT
|
||||
CapabilityBoundingSet=~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK
|
||||
CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM
|
||||
CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG
|
||||
CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE
|
||||
CapabilityBoundingSet=~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW
|
||||
CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -29,3 +29,7 @@ Once logged in, under the Web directory you will see a `www` folder which contai
|
|||
### Customizing the nginx configuration
|
||||
|
||||
If you want to add tweak the nginx configuration for this app, it is recommended to edit `/etc/nginx/conf.d/__DOMAIN__.d/__ID__.d/WHATEVER_NAME.conf` (ensure that the file has the `.conf` extension) and reload the nginx after making sure that the configuration is valid using `nginx -t`.
|
||||
|
||||
### Listening the right port for NodeJS
|
||||
|
||||
The listen port is available to the node process throught the environment variable `PORT`. Make sure that your main `.js` file retrieves it with `process.env.PORT` as its value is not predictable.
|
||||
|
|
|
@ -29,3 +29,7 @@ Après vous être connecté, sous le répertoire Web vous verrez un dossier `www
|
|||
### Personnaliser la configuration nginx
|
||||
|
||||
Si vous souhaitez ajuster la configuration nginx pour cette app, il est recommandé d'éditer `/etc/nginx/conf.d/__DOMAIN__.d/__ID__.d/WHATEVER_NAME.conf` (assurez-vous que le fichier a l'extension `.conf`) puis rechargez nginx après vous être assuré que la configuration est valide à l'aide de `nginx -t`.
|
||||
|
||||
### Écouter le bon port dans NodeJS
|
||||
|
||||
Le port d'écoute est accessible par le processus node au travers de la variable d'environment `PORT`. Veillez à ce que votre fichier `.js` principal le récupère bien avec `process.env.PORT` car sa valeur n'est pas prédictible.
|
||||
|
|
|
@ -4,4 +4,6 @@ It can also create a MySQL database - which will be backed up and restored with
|
|||
|
||||
PHP-FPM version can also be selected among `none`, `7.4`, `8.0`, `8.1` and `8.2`.
|
||||
|
||||
Finally, NodeJS can alternatively be used instead of PHP, with versions `18`, `20` or `21`.
|
||||
|
||||
**Once installed, go to the chosen URL to know the user, domain and port you will have to use for the SFTP access.** The password is one you chosen during the installation. Under the Web directory, you will see a `www` folder which contains the public files served by this app. You can put all the files of your custom Web application inside.
|
||||
|
|
|
@ -4,4 +4,6 @@ Elle peut également créer une base de données MySQL - qui sera sauvegardée e
|
|||
|
||||
La version de PHP-FPM peut aussi être choisie, parmi `none`, `7.4`, `8.0`, `8.1` et `8.2`.
|
||||
|
||||
Un serveur NodeJS peut finalement être utilisé à la place de PHP, avec les versions `18`, `20` ou `21`.
|
||||
|
||||
**Une fois installé, rendez-vous sur l'URL choisie pour connaître l'utilisateur, le domaine et le port que vous devrez utiliser pour l'accès SFTP.** Le mot de passe est celui que vous avez choisi lors de l'installation. Sous le répertoire Web, vous verrez un dossier `www` qui contient les fichiers publics servis par cette application. Vous pouvez mettre tous les fichiers de votre application Web personnalisée à l'intérieur.
|
||||
|
|
|
@ -48,10 +48,21 @@ ram.runtime = "50M"
|
|||
[install.phpversion]
|
||||
ask.en = "Choose a PHP version you want to use for your app"
|
||||
ask.fr = "Choisissez une version PHP que vous souhaitez utiliser pour votre application"
|
||||
help.en = "You can only choose NodeJS or PHP, not both"
|
||||
help.fr = "Vous ne pouvez avoir que NodeJS ou PHP, pas les deux"
|
||||
type = "select"
|
||||
choices = ["none", "7.4", "8.0", "8.1", "8.2"]
|
||||
default = "8.0"
|
||||
|
||||
[install.nodeversion]
|
||||
ask.en = "Choose a NodeJS version you want to use for your app"
|
||||
ask.fr = "Choisissez une version NodeJS que vous souhaitez utiliser pour votre application"
|
||||
help.en = "You can only choose NodeJS or PHP, not both"
|
||||
help.fr = "Vous ne pouvez avoir que NodeJS ou PHP, pas les deux"
|
||||
type = "select"
|
||||
choices = ["none", "18", "20", "21"]
|
||||
default = "none"
|
||||
|
||||
[install.database]
|
||||
ask.en = "Do you need a database?"
|
||||
ask.fr = "Avez-vous besoin d'une base de données ?"
|
||||
|
@ -64,6 +75,9 @@ ram.runtime = "50M"
|
|||
|
||||
[resources.install_dir]
|
||||
|
||||
[resources.ports]
|
||||
main.default = 3000
|
||||
|
||||
[resources.permissions]
|
||||
main.url = "/"
|
||||
|
||||
|
|
|
@ -36,6 +36,17 @@ then
|
|||
ynh_backup --src_path="/etc/php/${phpversion}/fpm/pool.d/$app.conf"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# BACKUP THE NodeJS CONFIGURATION
|
||||
#=================================================
|
||||
|
||||
if [ $nodeversion != "none" ]
|
||||
then
|
||||
ynh_backup --src_path="/etc/systemd/system/${app}-nodejs.service"
|
||||
ynh_backup --src_path="/etc/systemd/system/${app}-nodejs-watcher.service"
|
||||
ynh_backup --src_path="/etc/systemd/system/${app}-nodejs-watcher.path"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# BACKUP THE MYSQL DATABASE
|
||||
#=================================================
|
||||
|
|
|
@ -23,6 +23,7 @@ ssh_port=$(grep "^Port" /etc/ssh/sshd_config | awk '{print $2}')
|
|||
ynh_script_progression --message="Validating installation parameters..." --weight=2
|
||||
|
||||
[ $with_sftp -eq 0 ] || [ "$password" != "" ] || ynh_die --message="You need to set a password to enable SFTP"
|
||||
[ $phpversion != "none" ] || [ $nodeversion != "none" ] || ynh_die --message="Either PHP or NodeJS can be used, not both"
|
||||
|
||||
#=================================================
|
||||
# STORE SETTINGS FROM MANIFEST
|
||||
|
@ -68,8 +69,17 @@ then
|
|||
fi
|
||||
|
||||
# Create a dedicated NGINX config
|
||||
ynh_add_nginx_config
|
||||
ynh_add_config --template="example-custom-nginx-config.conf" --destination="$nginx_extra_conf_dir/sample.conf"
|
||||
# Use a custom nginx config when using nodejs as it is incompatible with the html/php one
|
||||
if [ $nodeversion == "none" ]
|
||||
then
|
||||
ynh_add_nginx_config
|
||||
ynh_add_config --template="example-custom-nginx-config.conf" --destination="$nginx_extra_conf_dir/sample.conf"
|
||||
else
|
||||
# Add the config manually because yunohost does not support custom nginx confs
|
||||
ynh_add_config --template="nginx-nodejs.conf" --destination="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
ynh_store_file_checksum --file="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# CREATE DEDICATED USER
|
||||
|
@ -134,6 +144,34 @@ then
|
|||
ynh_add_fpm_config --usage=$fpm_usage --footprint=$fpm_footprint --phpversion=$phpversion
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# NodeJS CONFIGURATION
|
||||
#=================================================
|
||||
|
||||
if [ $nodeversion != "none" ]
|
||||
then
|
||||
ynh_script_progression --message="Configuring NodeJS..." --weight=3
|
||||
|
||||
ynh_install_nodejs --nodejs_version=$nodeversion
|
||||
ynh_use_nodejs
|
||||
|
||||
ynh_add_config --template="../sources/www/package.json" --destination="$install_dir/www/package.json"
|
||||
ynh_add_config --template="../sources/www/index.js" --destination="$install_dir/www/index.js"
|
||||
|
||||
ynh_add_systemd_config --service="${app}-nodejs" --template="nodejs.service"
|
||||
ynh_add_systemd_config --service="${app}-nodejs-watcher" --template="nodejs-watcher.service"
|
||||
ynh_add_config --template="nodejs-watcher.path" --destination="/etc/systemd/system/${app}-nodejs-watcher.path"
|
||||
|
||||
systemctl enable "${app}-nodejs-watcher.path" --quiet
|
||||
systemctl daemon-reload
|
||||
|
||||
yunohost service add "${app}-nodejs" --description="$app NodeJS Server" --log="/var/log/$app-nodejs.log"
|
||||
ynh_add_config --template="nginx-nodejs.conf" --destination="$nginx_extra_conf_dir/nodejs.conf"
|
||||
ynh_systemd_action --service_name="${app}-nodejs"
|
||||
ynh_systemd_action --service_name="${app}-nodejs-watcher"
|
||||
ynh_systemd_action --service_name="${app}-nodejs-watcher.path"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
|
|
@ -46,6 +46,17 @@ ynh_script_progression --message="Removing PHP-FPM configuration..."
|
|||
# Remove the dedicated PHP-FPM config
|
||||
ynh_remove_fpm_config
|
||||
|
||||
#=================================================
|
||||
# REMOVE NodeJS CONFIGURATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Removing NodeJS configuration..."
|
||||
|
||||
yunohost service remove "${app}-nodejs"
|
||||
|
||||
ynh_remove_systemd_config --service="${app}-nodejs"
|
||||
ynh_remove_systemd_config --service="${app}-nodejs-watcher"
|
||||
ynh_secure_remove --file="/etc/systemd/system/${app}-nodejs-watcher.path"
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
|
|
@ -81,6 +81,17 @@ then
|
|||
ynh_restore_file --origin_path="/etc/php/${phpversion}/fpm/pool.d/$app.conf"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# RESTORE THE NodeJS CONFIGURATION
|
||||
#=================================================
|
||||
|
||||
if [ $nodeversion != "none" ]
|
||||
then
|
||||
ynh_restore_file --origin_path="/etc/systemd/system/${app}-nodejs.service"
|
||||
ynh_restore_file --origin_path="/etc/systemd/system/${app}-nodejs-watcher.service"
|
||||
ynh_restore_file --origin_path="/etc/systemd/system/${app}-nodejs-watcher.path"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
#=================================================
|
||||
|
|
|
@ -68,6 +68,12 @@ if [ -z "$phpversion" ]; then
|
|||
ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
|
||||
fi
|
||||
|
||||
# If phpversion doesn't exist, create it. We assume it is the default system one.
|
||||
if [ -z "$nodeversion" ]; then
|
||||
nodeversion="none"
|
||||
ynh_app_setting_set --app=$app --key=nodeversion --value=$nodeversion
|
||||
fi
|
||||
|
||||
# Delete old user
|
||||
if [ -n "$(ynh_app_setting_get --app=$app --key=user)" ]
|
||||
then
|
||||
|
@ -103,8 +109,17 @@ then
|
|||
fi
|
||||
|
||||
# Create a dedicated NGINX config
|
||||
ynh_add_nginx_config
|
||||
ynh_add_config --template="example-custom-nginx-config.conf" --destination="$nginx_extra_conf_dir/sample.conf"
|
||||
# Use a custom nginx config when using nodejs as it is incompatible with the html/php one
|
||||
if [ $nodeversion == "none" ]
|
||||
then
|
||||
ynh_add_nginx_config
|
||||
ynh_add_config --template="example-custom-nginx-config.conf" --destination="$nginx_extra_conf_dir/sample.conf"
|
||||
else
|
||||
# Add the config manually because yunohost does not support custom nginx confs
|
||||
ynh_add_config --template="nginx-nodejs.conf" --destination="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
ynh_store_file_checksum --file="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# CREATE DEDICATED USER
|
||||
|
@ -142,6 +157,34 @@ then
|
|||
ynh_add_fpm_config --usage=$fpm_usage --footprint=$fpm_footprint --phpversion=$phpversion
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# NodeJS CONFIGURATION
|
||||
#=================================================
|
||||
|
||||
if [ $nodeversion != "none" ]
|
||||
then
|
||||
ynh_script_progression --message="Updating NodeJS..." --weight=3
|
||||
|
||||
ynh_install_nodejs --nodejs_version=$nodeversion
|
||||
ynh_use_nodejs
|
||||
|
||||
ynh_add_config --template="../sources/www/package.json" --destination="$install_dir/www/package.json"
|
||||
ynh_add_config --template="../sources/www/index.js" --destination="$install_dir/www/index.js"
|
||||
|
||||
ynh_add_systemd_config --service="${app}-nodejs" --template="nodejs.service"
|
||||
ynh_add_systemd_config --service="${app}-nodejs-watcher" --template="nodejs-watcher.service"
|
||||
ynh_add_config --template="nodejs-watcher.path" --destination="/etc/systemd/system/${app}-nodejs-watcher.path"
|
||||
|
||||
systemctl enable "${app}-nodejs-watcher.path" --quiet
|
||||
systemctl daemon-reload
|
||||
|
||||
yunohost service add "${app}-nodejs" --description="$app NodeJS Server" --log="/var/log/$app-nodejs.log"
|
||||
ynh_add_config --template="nginx-nodejs.conf" --destination="$nginx_extra_conf_dir/nodejs.conf"
|
||||
ynh_systemd_action --service_name="${app}-nodejs"
|
||||
ynh_systemd_action --service_name="${app}-nodejs-watcher"
|
||||
ynh_systemd_action --service_name="${app}-nodejs-watcher.path"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
#=================================================
|
||||
|
|
19
sources/www/index.js
Normal file
19
sources/www/index.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
const http = require('node:http');
|
||||
const fs = require('fs');
|
||||
const index = fs.readFileSync('index.html').toString();
|
||||
|
||||
const host = '127.0.0.1';
|
||||
var port = process.env.PORT;
|
||||
port = (typeof port !== 'undefined') ? port : 3000;
|
||||
|
||||
const file = index.replace("<hr/>", `<hr/> <h2> Port configuration </h2> <p>Your node application have to listen on port ${port}. Alternatively, you can get port var from envirronment with the following: </p> <pre> process.env.PORT; </pre>`);
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.end(file);
|
||||
});
|
||||
|
||||
server.listen(port, host, () => {
|
||||
console.log('Web server running at http://%s:%s', host, port);
|
||||
});
|
11
sources/www/package.json
Normal file
11
sources/www/package.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "www",
|
||||
"version": "1.0.0",
|
||||
"description": "dummy app",
|
||||
"author": "",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"build": "exit 0"
|
||||
},
|
||||
"license": "ISC"
|
||||
}
|
Loading…
Add table
Reference in a new issue