Setup logrotate for nginx under windows

Create a batch script for the logrotate and save it as nginx_logrotate.bat

1
2
3
4
5
6
7
8
9
10
rem get date in format ddMMyyyyhhmmss
set dt=%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%
set dt=%dt: =0%
rem move the current logfiles
move F:\Programme\nginx\logs\Access.log F:\Programme\nginx\logs\Access%dt%.log
move F:\Programme\nginx\logs\Error.log F:\Programme\nginx\logs\Error%dt%.log
rem tell nginx to write new logfiles
cd F:\Programme\nginx\
call F:\Programme\nginx\nginx.exe -p F:\Programme\nginx\ -s reopen
Then you can create a basic windows scheduler task which starts this batch script.

If you run nginx as a windows service, make sure to execute the windows scheduler with the same user as the nginx windows service is running.

When you’re getting the following error: could not open error log file: CreateFile() “F:\Programme\nginx\nginx.exe/logs/error.log” failed (3: The system cannot find the path specified), make sure to not add nginx.exe to the parameter value

Setting up IIS as a reverse proxy

Overview tl;dr;

This post is all about setting up IIS(8.5) in order to be used as a reverse proxy.

Use multiple different Webservers (IIS/Apache/Tomcat) and run them on the same server and port.

Installing IIS

Just install IIS by using the add roles and feature functionality of windows server 2012

Installing apache

I currently have the problem that I own a windows 2012 virtual server, and need to run IIS and Apache on it. Installation is actually super easy, just install IIS and then Apache (I took the apache binaries for windows from apachehaus)

But if you now try to start apache, the following error will show up:

(OS 10013)An attempt was made to access a socket in a way forbidden by its access permissions. : AH00072: make_sock: could not bind to address [::]:80

This happens because I’m trying to open port 80 with apache while port 80 is already used by IIS. And the same would happen when I try to start Tomcat or any other server which tries to run on port 80.

This error can be avoided by setting the Listen Port of apache to anything different than port 80, i.e. 8080. Problem with this solution is that any site served by apache can only be reached via port 8080 which is super uncool since a user then has to enter the port 8080 together with the domain name.

Setup IIS

In order to use IIS as a reverse proxy, the rewrite module must be installed. This can be done by downloading it from the microsoft website

To get rewrite(Not only redirect) working, the application request routing must be installed as well from the microsoft website

Now the Application Request Routing must be configured in IIS manager. It’s as simple as checking the Enable proxy checkbox.

Now a new website must be added in IIS pointing to an empty directory. In order for IIS to act properly as a proxy, this website must be bound to a host name. (For this demo and since I don’t have a hostname, I just added a entry into the host file of the computer)

When now connecting to this site, noting must be shown since there is no content in the configured folder.

Next step is to setup the rewrite rule.

Setup rewrite rule in IIS

Add a new Blank rule via URL rewrite

The rule must look like the following sample.

This is the corresponding web.config to the screenshot below:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--?xml version="1.0" encoding="UTF-8"?-->
<configuration>
<system.webserver>
<rewrite>
<rules>
<rule name="test" patternsyntax="Wildcard" stopprocessing="true">
<match url="*">
<action url="http://proxytest.com:8080/{R:0}" type="Rewrite">
</action></match></rule>
</rules>
</rewrite>
</system.webserver>
</configuration>

Done

Now it’s done. Requests sent to proxytest.com:80 will be rewritten from IIS to the address from rewrite URL.

With this configuration, it’s possible to run IIS, Apache, Tomcat and many other webserver at the same time on the same server under the same port.

Exception: That assembly does not allow partially trusted callers

I have .net 3.5 program where i load some assemblies from a network share via reflection. Now i’ve got the following exception: “That assembly does not allow partially trusted callers’’(Detailed message below). The calling assembly(.exe) is local. This .exe loads the assembly from network via reflection. The assembly from the network share then has a reference on a third assembly which is located beneath the .exe. (Hard to explain, image will do better…)

The reason for this failure is the .net security. It doesn’t allow the MyLib.dll to be loaded, because the calling assembly is located on a network share and is signed with a strong name.

Solution 1

Allow all code to be executed using caspol. This might be dangerous, but if you’re desperate it could be a solution.

1
"C:\Windows\Microsoft.NET\Framework\v2.0.50727\CasPol.exe" -machine -chggroup All_Code FullTrust

Solution 2

No signing If you remove the signature from MyLib2.dll, everything works.

Solution 3

set attribute AllowPartiallyTrustedCallers If you set the AllowPartiallyTrustedCallers in the AssemblyInfo.cs of the signed assembly, everything works.

1
2
3
using System.Security;

[assembly: AllowPartiallyTrustedCallers()]

Usefull links

caspol doku
howto set fulltrust to a share
Using Libraries from Partially Trusted Code
Allowing Partially Trusted Callers

Get the current directory from a c# application

Overview

Sometimes i have to read/write files from the root directory of my application. Usually i did this with Environment.CurrentDirectory. Unfortunately, this only works if the application is a standalone application(.exe). In case the application is a windows service or a asp.net website, the path from Environment.CurrentDirectory is wrong.

There are several ways to get the root directory of an application, but so far i found only one which works in all scenarios. The only one which always works is:

1
2
//works...
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath)

Here is a (incomplete) list of ways to get the root path of a c# application:

Windows service

1
2
3
4
5
6
7
8
Environment.CurrentDirectory:
//C:\Windows\system32
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath)
//D:\project\WindowsServiceTest\WindowsServiceTest\bin\Debug
AppDomain.CurrentDomain.BaseDirectory:
//D:\project\WindowsServiceTest\WindowsServiceTest\bin\Debug\
Process.GetCurrentProcess().MainModule.FileName.Substring(0, Process.GetCurrentProcess().MainModule.FileName.LastIndexOf("\")):
//D:\project\WindowsServiceTest\WindowsServiceTest\bin\Debug`

Console application

1
2
3
4
5
6
7
8
Environment.CurrentDirectory:
//D:\project\ConsoleApplication3\ConsoleApplication3\bin\Debug
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath):
//D:\project\ConsoleApplication3\ConsoleApplication3\bin\Debug
AppDomain.CurrentDomain.BaseDirectory:
//D:\project\ConsoleApplication3\ConsoleApplication3\bin\Debug\
Process.GetCurrentProcess().MainModule.FileName.Substring(0, Process.GetCurrentProcess().MainModule.FileName.LastIndexOf("\")):
//D:\project\ConsoleApplication3\ConsoleApplication3\bin\Debug

asp.net mvc3 website vs2010 integrated webserver (Debug mode)

1
2
3
4
5
6
7
8
Environment.CurrentDirectory:
//C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath):
//D:\project\MvcApplication1\MvcApplication1\bin
AppDomain.CurrentDomain.BaseDirectory:
//D:\project\MvcApplication1\MvcApplication1\
Process.GetCurrentProcess().MainModule.FileName.Substring(0, Process.GetCurrentProcess().MainModule.FileName.LastIndexOf("\")):
//C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0

asp.net mvc3 website IIS (Release mode)

1
2
3
4
5
6
7
8
Environment.CurrentDirectory: 
//c:\windows\system32\inetsrv
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath):
//d:\project\MvcApplication1\MvcApplication1\bin
AppDomain.CurrentDomain.BaseDirectory:
//d:\project\MvcApplication1\MvcApplication1\
Process.GetCurrentProcess().MainModule.FileName.Substring(0, Process.GetCurrentProcess().MainModule.FileName.LastIndexOf("\")):
//c:\windows\system32\inetsrv