Skip to content

DSM CGI Router 7.x

Valéry Letroye edited this page Aug 27, 2023 · 11 revisions

Principle

The principle is the very same for DSM 7.x as for DSM 6.x. Read therefore the details here.

Simple version

This case is exactly the same as for the DSM 6.x.

See MODS Sample - Basic CGI 7.x for illustration purpose.

Advanced version

This case is nearly the same as for the DSM 6.x:

  • The CGI script and the config file for nginx are exactly the same.
  • But the package need root access rights to be able to copy or link the config file for nginx under: /usr/syno/share/nginx/conf.d/.

And since DSM 7.x, Synology prevents end users to install their own packages as root. Instead, the installation scripts are running with their own system internal accounts (For each package, an account having the same name is created and used). It is possible to see those accounts via the Permissions Editor of the "Shared Folders": DSM > Control Panel > Shared Folder > Edit (any Share) > Permissions > <System internal user>

View System Internal Accounts

This was not the case with DSM 6.x and older versions as installation scripts were run as root by default. There are fortunately two workarounds explained on my Blog:

  • Either specify, in package's privilege file, an installation account granted sudo rights without password on the command ln and unlink.
  • Or, during installation, execute the commands to be run as root via a SSH Console, using an admin account.

None of these workarounds are totally secure... So use them at your own risk.

Install with a sudoer account:

The only steps which require root access are the creation/deletion of a link under nginx's config folder. Indeed, no need to actually copy the config file there; it can be kept in the target deployment folder of the package. Concretely:

  1. Connect onto your NAS via SSH (using e.g. the Putty console) as administrator
  2. Create a sudo file (the name does not matter): sudo vi /etc/sudoers.d/ModsPackager
  3. Grant access rights on the commands ln and unlink, without having to type a password, with this: ModsPackager ALL=(ALL) NOPASSWD: /bin/ln, /bin/unlink
  4. Save the file (with :x!)

Notice that you should really be careful as any error in that file will prevent you to log in anymore: DANGER !!! That's why it is usually highly recommended to use the command 'visudo' to edit such files (it checks the syntax before saving changes)... Unfortunately, this command is not available on Synology.

Next, configure your Package with a "privilege" file (/conf/privilege) containing

{
  "defaults": {
    "run-as": "package"
  },
  "username": "ModsPackager",
  "groupname": "ModsPackager"
}

And now, respectively in your postinst and preuninst scripts, you can link (sudo ln -s) and unlink (sudo unlink) your config file under /usr/syno/share/nginx/conf.d/.

See MODS Sample - Simple CGI 7.x for illustration purpose.

Install via a SSH console:

With this technique, the internal system account running the installation doesn't need to be a sudoer. The idea is simple: execute the commands via a SSH console running with an administrator account (which is by definition a sudoer).

To implement this idea, an installation wizard must prompt the user for an administrator account and password. Next, the installation scripts can use those credentials to open a SSH connection and execute any provided commands or scripts. The easiest way to execute commands via SSH being to use a php scripts and the ssh2.so module. Here is a shell script function for illustration purpose:

function ExecSSH() {
	user=$1	# Admin account
	pass=$2	# Admin password
	port=$3 # SSH port
	cmd=$4	# Command to execute
	
	# Find the php version to be used 
	version=`php -v | grep "PHP " | cut -f2 -d " "`
	major=`echo $version | cut -d. -f1`
	minor=`echo $version | cut -d. -f2`
	
	if [ $0 == "-sh" ]; then
		# If run from a -sh, assume that the php script os local
		path="."
	else
		path="/var/packages/$SYNOPKG_PKGNAME/scripts"
	fi
	script="$path/exec.php"
		
	# Call PHP with ssh2 modules
	output="$(php -dextension=/var/packages/PHP$major.$minor/target/usr/local/lib/php$major$minor/modules/ssh2.so "$script" -u "$user" -p "$pass" -s "127.0.0.1" -o "$port" -c "$cmd")"
	ExitCode=$? #Do not add any line or comment between the command and this line retrieving its exit code!!
	
	LogInfo "$output"
	return $ExitCode
}

Here is a sample of call to be used in the postinst script (variables $MODS_* coming from the installation wizard):

ExecSSH "$MODS_ADMIN" "$MODS_PASSWORD" "$MODS_PORT" "ln -s $SYNOPKG_PKGDEST/ui/dsm.cgi.conf /usr/syno/share/nginx/conf.d/dsm.$SYNOPKG_PKGNAME.conf"

See MODS Sample - Advanced CGI 7.x for illustration purpose.