Skip to content

On Ubuntu

In this chapter, we’ll demonstrate how to install RESTCaptcha on Ubuntu Server 24.04 LTS using nginx as a reverse proxy.

Installing nginx

Check whether nginx is already installed:

nginx -v

If the result looks like this, you’re all set and can proceed to the next section, “Installing ASP.NET”:

nginx version: nginx/1.28.0

If instead you see Command 'nginx' not found, you need to install nginx:

sudo apt update && sudo apt install nginx

To start nginx, enter the following:

sudo systemctl start nginx

To enable automatic startup when your server boots:

sudo systemctl enable nginx

Then test whether you can access nginx’s default webpage locally:

wget -S --spider localhost

nginx default website

The nginx default site is not required for RESTCaptcha. You can—and should—disable it:

sudo unlink /etc/nginx/sites-enabled/default
sudo systemctl reload nginx

Installing ASP.NET

RESTCaptcha requires the ASP.NET framework as a dependency.

The installation of ASP.NET Core 9 is described in detail in the Microsoft documentation. Here’s the short version:

First, add the package repository:

sudo add-apt-repository ppa:dotnet/backports

Then install the ASP.NET Core runtime:

sudo apt-get update && sudo apt-get install -y apt-transport-https 
sudo apt-get update && sudo apt-get install -y aspnetcore-runtime-9.0

Installing RESTCaptcha

Copying the binaries

Create a new directory for RESTCaptcha (e.g. /usr/share/restcaptcha) and copy the binaries from the latest release into it.

The following Bash one-liner will do this for you:

curl -sL -H "User-Agent: curl" https://api.github.com/repos/openpotato/restcaptcha/releases/latest | jq -r '.assets[] | select(.name | endswith(".zip")) | .browser_download_url' | head -n1 | xargs -I{} bash -c 'tmp=$(mktemp /tmp/restcaptcha.XXXX.zip); curl -L -H "User-Agent: curl" -o "$tmp" "{}"; sudo mkdir -p /usr/share/restcaptcha; sudo unzip -o "$tmp" -d /usr/share/restcaptcha; rm "$tmp"'

Now configure ownership and access permissions for the directory:

sudo chown -R nginx:nginx /usr/share/restcaptcha
sudo chmod -R u=rwX,g=rX,o= /usr/share/restcaptcha

Create a new file /usr/share/restcaptcha/appsettings.Production.json:

{
  "Serilog": {
    "Using": [
      "Serilog.Sinks.Console",
      "Serilog.Sinks.File"
    ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft.AspNetCore": "Warning",
        "Microsoft.AspNetCore.Hosting.Diagnostics": "Warning",
        "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
      }
    },
    "WriteTo": [
      { "Name": "Console" },
      {
        "Name": "File",
        "Args": {
          "path": "/var/log/restcaptcha/log-.txt",
          "rollingInterval": "Day",
          "retainedFileCountLimit": 14,
          "fileSizeLimitBytes": 10000000,
          "rollOnFileSizeLimit": true
        }
      }
    ]
  },
  "RestCaptcha": {
    "Sites": [
      {
        "name": "My Site",
        "description": "My site using RESTCaptcha",
        "siteKey": "My-Site-Key",
        "siteSecret": "AeyGWx3kQeyrDFCE5KDR",
        "validHostNames": []
      }
    ]
  }
}

Next, create a systemd service file for the API web service:

sudo nano /etc/systemd/system/restcaptcha.service

Insert the following content:

[Unit]
Description=RESTCaptcha Web Service

[Service]
WorkingDirectory=/usr/share/restcaptcha
ExecStart=/usr/bin/dotnet RestCaptcha.WebService.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=restcaptcha
User=nginx
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS=http://localhost:5030

[Install]
WantedBy=multi-user.target

Then start the API web service:

sudo systemctl daemon-reload
sudo systemctl enable restcaptcha.service
sudo systemctl start restcaptcha.service

Verify that it’s running successfully:

sudo systemctl status restcaptcha.service

Nginx as a reverse proxy

Create a new nginx configuration file and add the following content:

server {
    server_name  localhost;
    listen       127.0.0.1:8080;
    listen       [::1]:8080;
    root         /usr/share/restcaptcha.webservice;

    # Proxy request to Kestrel
    location / {
        proxy_pass         http://127.0.0.1:5030;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }

    # Redirect server error pages to the static page /50x.html
    error_page 500 502 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

server {
    server_name  captcha.example.com;
    listen       443 ssl; 
    root         /usr/share/restcaptcha.webservice;

    # Proxy request to Kestrel
    location / {
        proxy_pass         http://127.0.0.1:5030;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }

    # Redirect server error pages to the static page /50x.html
    error_page 500 502 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    # Enable HTTP/2 protocol
    http2 on;
}

Restart nginx:

sudo systemctl restart nginx

You can now test the RESTCaptcha health endpoint locally:

Invoke-WebRequest -Uri "http://localhost:8080/health" -UseBasicParsing

For public access, you’ll still need a TLS certificate for your HTTPS binding. A good option is to use Let’s Encrypt to generate free TLS certificates.

To do so, install an ACME client. One of the best for Linux is Certbot. Install and run Certbot; once you’ve answered all questions, it will communicate with Let’s Encrypt, request a TLS certificate for the domain captcha.example.com, and automatically update your nginx configuration.

A test in your web browser at https://captcha.example.com/health should now succeed.