Custom NGINX config for Synology Web Station on DSM 7.2
We may earn commissions from the companies mentioned in this post. View our FTC disclosure for more information.
If you’re anything like me, you don’t like to install extra packages, like Apache, when you already have a perfectly good instance of NGINX running. I’ve been using Synology Web Station for many years, and have always had a custom nginx.conf file in each website’s root directory. In DSM versions past, it didn’t matter, as the config file’s where I wrote my include never changed. I recently upgraded my Synology NAS to the latest OS version, DSM 7.2-64561, and now things are much different. Not only did the old configs get completely wiped out, the new ones are overwritten each time a package is updated…any package as far as I can tell! What’s more, the name of the config files change as well. It’s a real mystery, but I’ve solved it and will share it with you today!
What we must do is find some way to get our include statement inserted after updates/upgrades. I don’t have an automated way to do that at this time, but I thought I’d at least share the bash script that I wrote to do the heavy lifting. It iterates over the conf.d directory looking in each file, and looks for the line matching your defined web root directory. It splits that out and appends the include statement to the end of the file, if it doesn’t already exist! Lastly, it restarts NGINX so the new settings can be applied.
You shouldn’t need to modify anything more than the first two variables, if any at all. I hope you find it useful. Please let me know in the comments 🙂
#!/bin/bash
# Edit this variable if necessary. Path to web directory
web_dir=/volume1/web
# Edit this variable if necessary. The name of your desired config file
conf_file=nginx.conf
# Include filenames beginning with a '.' in the results
shopt -s dotglob
# Define search pattern
search_pattern="$web_dir/([a-zA-Z\.]+)"
# Directory of config files
directory_path=/usr/local/etc/nginx/conf.d
# Iterate over contents of directory
for file_path in "$directory_path"/*; do
# Check if item is of type file
if [ -f "$file_path" ]; then
# Check if there's a match for the search pattern
if grep -qE "$search_pattern" "$file_path"; then
# Get the site directory path for the website corresponding to this config file
site_dir=$(grep -oE "$search_pattern" "$file_path" | tail -n 1)
# Create an include statement
new_line="include $site_dir/$conf_file;"
# If the new line doesn't already exist, append to the end of the file
if ! grep -q "$new_line" "$file_path"; then
echo "$new_line" >> "$file_path"
echo "$new_line added to $file_path"
# Otherwise, do nothing
else
echo "include exists for $site_dir"
fi
fi
fi
done
# Restart nginx
nginx -s reload && nginx -t
If you find a quick and dirty way to make sure that this gets run after the files change or are overwritten, I’d love to hear it! Here’s my solution: I created a triggered task that’s started on boot-up. It points to the following script which checks the md5 checksum of the files every 10 seconds. You just need to edit the part that says /PATH/TO/THE/SCRIPT/ABOVE.sh
#!/bin/bash
# Wait for boot-up to complete starting packages
sleep 120
# Path to files
file_path="/usr/local/etc/nginx/conf.d"
# File pattern
file_pattern=".service.*.conf"
# Store the initial MD5 hashes of the files
declare -A initial_md5_hashes
# Function to check if a file has changed
file_has_changed() {
local file="$1"
local current_md5_hash=$(md5sum "$file" | awk '{print $1}')
if [[ $current_md5_hash != ${initial_md5_hashes["$file"]} ]]; then
return 0 # File has changed
else
return 1 # File has not changed
fi
}
# Get the initial list of files matching the pattern
files=()
while IFS= read -r -d '' file; do
files+=("$file")
initial_md5_hashes["$file"]=$(md5sum "$file" | awk '{print $1}')
done < <(find $file_path -name $file_pattern -print0)
while true; do
# Flag to indicate if changes have occurred
changes_occurred=false
# Check if any file has changed
for file in "${files[@]}"; do
if file_has_changed "$file"; then
echo "File '$file' has changed."
changes_occurred=true
fi
done
# Call script if changes have occurred
if [ "$changes_occurred" = true ]; then
echo "Executing the script..."
/PATH/TO/THE/SCRIPT/ABOVE.sh
fi
# Sleep for some time before checking again
sleep 10
done
I’ll give you a better and fastest solution. DSM7.2
just create the following file , replace XXXXX with any name you want. have your nginx config in there. restart your webstation in DSM.
/etc/nginx/conf.d/.webstation.error_page.default.XXXXXX.conf
voila..
I like that, thanks! The trouble I was facing is that I have many websites each with their own config. Could your solution work under those circumstances somehow?
Thank you for this interesting post!
what are the difference between your command to restart nginx and “synosystemctl restart nginx” ?
– I use nginx proxy manager (aka n.p.m.) on my synology docker so I have redirected all traffic from my router (ports 80 and 443) to the synology nginx proxy manager ports. It works fine but, I have a wordpress site hosted in webstation.
As webstation still use its own nginx on ports 80/443 my wordpress site url returns now a 404
Should I try to write a kind of ip table rule to force redirect to 80/443 instead of custom npm ports just when origin referrer is my wordpress website url (which is e.g. mywordpresssite.mydomain.fr) (so my website won’t use npm and still would use webstation nginx)
– or should I try to force webstation to use nginx from npm by changing webstation config file?
What are your thoughts about this please?
I believe the differences between “synosystemctl restart nginx” and “nginx -s reload && nginx -t” are that the first one is Synology’s abstraction of the second. Also, the second one does a test of the config file to ensure it doesn’t have any syntax errors and immediately prints the output of the test.
For your wordpress site, I don’t have experience with nginx proxy manager, but can you set up a reverse proxy using the native Synology Application Portal (Control Panel > Application Portal > Reverse Proxy) to see if it would intercept the traffic? Then you could set custom ports in webstation for that site and have the reverse proxy rule point to it. I’m just taking a wild guess 🙂 I hope something here helps get you closer!