504 Gateway Timeout on Synology NAS

Looks familiar?

I want to move this blog to my own NAS because I have plenty enough bandwidth and with Cloudflare as reverse proxy it is secure enough also (and I like to hobby off course 😉 ).

I tried to use the Duplicator WordPress plugin to make a dump of my website and do a restore in the Synology Webstation. But during the database restore in step 2 every time I was getting a 504 gateway timeout after a minute (exactly 60 seconds).

What I could have done was a manual (ftp & database) copy and restore the files. But I was sure I was getting other errors in the future when I had to update WordPress or other plugins. So fixing this timeout issue was the only solution.

On different places on the internet, I found that I had change the Nginx site settings. So I put the timeout settings in the associated “/etc/nginx/conf.d/site.conf” and restart Nginx and restore the database Nginx was still was failing.

    proxy_connect_timeout 600s;
    proxy_send_timeout 600s;
    proxy_read_timeout 600s;
    send_timeout 600s;

Then I’ll try to put these lines in the “/etc/nginx/nginx.conf” but when I restart the nginx the settings were overwritten and my changes are gone.

Every time you restart, Nginx Synology make use of a file “/usr/syno/share/nginx/nginx.mustache” to create a new nginx.conf file. I change the lines in that file and *boom* everything was working 🙂

So TLDR;

sudo su -
vim /usr/syno/share/nginx/nginx.mustache

#add these lines
    send_timeout                  600s;
    proxy_connect_timeout         600s;
    proxy_send_timeout            600s;
    proxy_read_timeout            600s;

synoservice --restart nginx

If you want to see the current Nginx config

nginx -T 

Have fun 🙂

Create Azure Linux VM with worpress pre-installed

This is my first completed automated Linux Azure VM deployment. I like to share it with you.

There are 3 parts

  1. Create a keygen for ssh
  2. Powershell script
  3. Bash script

First start powershell and create a keypair with passphase

ssh-keygen -m PEM -t rsa -b 4096

Then place the bash script somewhere on your local computer

#! /bin/bash
apt-get update
apt-get install -y wordpress php libapache2-mod-php mysql-server php-mysql

echo "Alias /blog /usr/share/wordpress" >>/etc/apache2/sites-available/wordpress.conf
echo "<Directory /usr/share/wordpress>" >>/etc/apache2/sites-available/wordpress.conf
echo "    Options FollowSymLinks" >>/etc/apache2/sites-available/wordpress.conf
echo "    AllowOverride Limit Options FileInfo" >>/etc/apache2/sites-available/wordpress.conf
echo "    DirectoryIndex index.php" >>/etc/apache2/sites-available/wordpress.conf
echo "    Order allow,deny" >>/etc/apache2/sites-available/wordpress.conf
echo "    Allow from all" >>/etc/apache2/sites-available/wordpress.conf
echo "</Directory>" >>/etc/apache2/sites-available/wordpress.conf
echo "<Directory /usr/share/wordpress/wp-content>" >>/etc/apache2/sites-available/wordpress.conf
echo "    Options FollowSymLinks" >>/etc/apache2/sites-available/wordpress.conf
echo "    Order allow,deny" >>/etc/apache2/sites-available/wordpress.conf
echo "    Allow from all" >>/etc/apache2/sites-available/wordpress.conf
echo "</Directory>" >>/etc/apache2/sites-available/wordpress.conf

a2ensite wordpress
a2enmod rewrite 
reload apache2 
service apache2 reload
systemctl restart apache2

mysql -e "CREATE DATABASE wordpress;"
mysql -e "CREATE USER [email protected] IDENTIFIED BY '[email protected]';"
mysql -e "GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER ON wordpress.* TO [email protected];"
mysql -e "FLUSH PRIVILEGES;"

echo "<?php" >>/etc/wordpress/config-localhost.php
echo "define('DB_NAME', 'wordpress');">>/etc/wordpress/config-localhost.php
echo "define('DB_USER', 'wordpress');">>/etc/wordpress/config-localhost.php
echo "define('DB_PASSWORD', '[email protected]');">>/etc/wordpress/config-localhost.php
echo "define('DB_HOST', 'localhost');">>/etc/wordpress/config-localhost.php
echo "define('DB_COLLATE', 'utf8_general_ci');">>/etc/wordpress/config-localhost.php
echo "define('WP_CONTENT_DIR', '/usr/share/wordpress/wp-content');">>/etc/wordpress/config-localhost.php
echo "?>">>/etc/wordpress/config-localhost.php

service mysql start


publicip=$(dig +short myip.opendns.com @resolver1.opendns.com) && mv /etc/wordpress/config-localhost.php /etc/wordpress/config-$publicip.php

Then put the code in the Powershell ISE, change some variables and kickoff the script.

The things you may need to change:

  • script.sh location

New-AzResourceGroup -Name lxautodeploy -Location westeurope

# Create a subnet configuration
$subnetConfig = New-AzVirtualNetworkSubnetConfig `
  -Name "mySubnet" `
  -AddressPrefix 192.168.1.0/24

# Create a virtual network
$vnet = New-AzVirtualNetwork `
  -ResourceGroupName "lxautodeploy" `
  -Location "westeurope" `
  -Name "myVNET" `
  -AddressPrefix 192.168.0.0/16 `
  -Subnet $subnetConfig

# Create a public IP address and specify a DNS name
$pip = New-AzPublicIpAddress `
  -ResourceGroupName "lxautodeploy" `
  -Location "westeurope" `
  -AllocationMethod Static `
  -IdleTimeoutInMinutes 4 `
  -Name "mypublicdns$(Get-Random)"


# Create an inbound network security group rule for port 22
$nsgRuleSSH = New-AzNetworkSecurityRuleConfig `
  -Name "myNetworkSecurityGroupRuleSSH"  `
  -Protocol "Tcp" `
  -Direction "Inbound" `
  -Priority 1000 `
  -SourceAddressPrefix * `
  -SourcePortRange * `
  -DestinationAddressPrefix * `
  -DestinationPortRange 22 `
  -Access "Allow"

# Create an inbound network security group rule for port 80
$nsgRuleWeb = New-AzNetworkSecurityRuleConfig `
  -Name "myNetworkSecurityGroupRuleWWW"  `
  -Protocol "Tcp" `
  -Direction "Inbound" `
  -Priority 1001 `
  -SourceAddressPrefix * `
  -SourcePortRange * `
  -DestinationAddressPrefix * `
  -DestinationPortRange 80 `
  -Access "Allow"

# Create a network security group
$nsg = New-AzNetworkSecurityGroup `
  -ResourceGroupName "lxautodeploy" `
  -Location "westeurope" `
  -Name "myNetworkSecurityGroup" `
  -SecurityRules $nsgRuleSSH,$nsgRuleWeb

  # Create a virtual network card and associate with public IP address and NSG
$nic = New-AzNetworkInterface `
  -Name "myNic" `
  -ResourceGroupName "lxautodeploy" `
  -Location "westeurope" `
  -SubnetId $vnet.Subnets[0].Id `
  -PublicIpAddressId $pip.Id `
  -NetworkSecurityGroupId $nsg.Id

  # Define a credential object
$securePassword = ConvertTo-SecureString ' ' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("azureuser", $securePassword)

# Create a virtual machine configuration
$vmConfig = New-AzVMConfig `
  -VMName "myLXVM" `
  -VMSize "Standard_D2s_v3" | `
Set-AzVMOperatingSystem `
  -Linux `
  -ComputerName "myLXVM" `
  -Credential $cred `
  -DisablePasswordAuthentication | `
Set-AzVMSourceImage `
  -PublisherName "Canonical" `
  -Offer "UbuntuServer" `
  -Skus "18.04-LTS" `
  -Version "latest" | `
Add-AzVMNetworkInterface `
  -Id $nic.Id

# Configure the SSH key
$sshPublicKey = cat ~/.ssh/id_rsa.pub
Add-AzVMSshPublicKey `
  -VM $vmconfig `
  -KeyData $sshPublicKey `
  -Path "/home/azureuser/.ssh/authorized_keys"

New-AzVM `
  -ResourceGroupName "lxautodeploy" `
  -Location westeurope -VM $vmConfig

Get-AzPublicIpAddress -ResourceGroupName "lxautodeploy" | Select "IpAddress"



Invoke-AzVMRunCommand -ResourceGroupName "lxautodeploy" -Name 'myLXVM' -CommandId 'RunShellScript' -ScriptPath "script.sh" -Verbose

Now you can go to http://<publicip>/blog to access the new blog

You can access the server with ssh [email protected]<publicip>

Have fun with it!

Citrix reboot server script

This Citrix script will reboot all the servers with the tags SomeTag or SomeOtherTag and are in maintenance mode. Have fun!

$machines=Get-BrokerMachine | Where-Object {($_.Tags -eq "SomeTag" -or $_.Tags -eq "SomeOtherTag") -and ($_.InMaintenanceMode -eq "True")}
Foreach($machine in $machines)
{New-BrokerHostingPowerAction -Action Restart -MachineName $machine.Machinename}

Install Pihole on Synology with docker

Unfortunately, there isn’t a pihole addon in the Synology package center. But you can build your pihole in a docker container instead 🙂

The reason you must use docker-compose instead of the Synology docker package itself is that you want to bridge net NIC of your Synology and place the pihole direct in your network. You cannot do this with the GUI.

The steps:

  • Install docker with the package center
  • Activate SSH
  • Download de image pihole/pihole:latest
  • Login with ssh
  • type vi docker-compose.yaml
  • Paste the content from the docker-compose.yaml example into the vi
  • Change the IP adressen to your own network
  • Type :wr to save the file
  • Type :q to quit vi
  • Type “sudo docker-compose up”
  • Have fun!

Docker-compose.yaml Example

# Note: 192.168.123.xxx is an example network, you must update all these to match your own.

version: '2'

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    hostname: pihole
    domainname: localhost             # <-- Update
    mac_address: d0:ca:ab:cd:ef:01
    cap_add:
      - NET_ADMIN
    networks:
      pihole_network:
        ipv4_address: 192.168.123.199   # <-- Update
    dns:
      - 127.0.0.1
      - 1.1.1.1
    ports:
      - 443/tcp
      - 53/tcp
      - 53/udp
      - 67/udp
      - 80/tcp
    environment:
      ServerIP: 192.168.123.199                 # <-- Update (match ipv4_address)
      VIRTUAL_HOST: pihole.localhost            # <-- Update (match hostname + domainname)
      WEBPASSWORD: "justarondompassword"        # <-- Add password (if required)
    restart: unless-stopped

networks:
  pihole_network:
    driver: macvlan
    driver_opts:
      parent: ovs_eth0
    ipam:
      config:
        - subnet: 192.168.123.0/24            # <-- Update
          gateway: 192.168.123.1              # <-- Update
          ip_range: 192.168.123.192/28        # <-- Update

When you want to update the docker container, all you have to do is:

sudo docker-compose down

and

sudo docker-compose up

A good article I used to figure everything out is: http://tonylawrence.com/posts/unix/synology/free-your-synology-ports/

Policy WSUS: “Automatically download updates and install them on the schedule specified below” don’t work…!!!?!

So I configure a “configure automatic updates” policy for testing purposes but the auto-update and installation won’t work. The main cause….? Lack of patience 😉

How this Policy works (source):

The Windows Update Agent periodically checks the WSUS server for updates. Updates it finds, it reports state for: Installed, Not Installed, Not Applicable. If a “Not Installed” update is approved and available, the WUA queues the installation files for download if the Configure Automatic Updates policy is set to AUOption ‘3’ or ‘4’.

The download occurs via Background Intelligent Transfer Service (BITS) subsequent to the WUA finding the update as available for download.

When the download of the update is completed, the WUA does one of two things:

  • If the Configure Automatic Updates policy is set to AUOption ‘4’, then the WUA will schedule the update for installation at the scheduled time. This scheduled installation does NOT require access to the WSUS server to be conducted.
  • If the Configure Automatic Updates policy is not set to AUOption ‘4’, then the update will be retained on the client computer until a user launches the Windows Update applet from Control Panel and initiates the installation.

So bottom line; the updates must first be downloaded on the client and ONLY then will Windows apply the “Automatically download updates and install them on the schedule specified” action

To force a client (source):

$updateSession = new-object -com "Microsoft.Update.Session"; $updates=$updateSession.CreateupdateSearcher().Search($criteria).Updates
Start-sleep -seconds 10
wuauclt /detectnow
wuauclt /reportnow
c:\windows\system32\UsoClient.exe startscan

After this commands BITS will download the updates and prepare the installation. When you start Windows update you can see the available update

The default of the WSUS communication check-in (report and detect) is 22 hours. If you don’t want to wait so long you can change the “automatic updates detection frequency” to every hour (do not to this every hour on production policies!)

And now wait till the magic happens 🙂

Last but now least. When you change setting in the “configure automatic updates” policy you can trigger the client with powershell so you don’t have to reboot the client

gpupdate /force
net stop wuauserv
net start wuauserv
(new-object -Comobject Microsoft.Update.AutoUpdate).Detectnow()

You get get more information about Windows update log with the command.

Get-WindowsUpdateLog

Happy updating!

OK… Even with all the tips. Sometimes you need rename the software distribition folder also so I present to you: The PLZ GIVE ME ******* UPDATES NOW SCRIPT!!!!

gpupdate /force
Start-sleep -seconds 10
net stop wuauserv
mv C:\Windows\SoftwareDistribution C:\Windows\SoftwareDistribution.0ld
net start wuauserv
$updateSession = new-object -com "Microsoft.Update.Session"; $updates=$updateSession.CreateupdateSearcher().Search($criteria).Updates
Start-sleep -seconds 10
wuauclt /detectnow
wuauclt /reportnow
(new-object -Comobject Microsoft.Update.AutoUpdate).Detectnow()