Ubuntu CLI (2026)


Certbot Wildcards Certifiactes (OVH)

Wildcard Let’s Encrypt Certificate with OVH DNS (Certbot)

0. Introduction

Goal

Obtain and automatically renew a wildcard TLS certificate (*.qool.ovh) using Let’s Encrypt, with DNS hosted at OVH and the server hosted elsewhere (e.g. Contabo).

Key Requirements

Wildcard certificates require DNS-01 validation. This means Certbot must be able to create and remove DNS TXT records via the OVH API.

High-Level Overview

The process consists of:

  1. Installing Certbot (Snap version)
  2. Creating a correct OVH API token
  3. Storing OVH credentials securely
  4. Verifying API access with Python
  5. Running Certbot with the OVH DNS plugin
  6. Cleaning up and relying on auto-renewal
  7. 1. Install Certbot (Snap)

1. Installing Certbot (Snap version)

Remove old packages

sudo apt remove certbot

Install Snap and Certbot

sudo apt update
sudo apt install snapd
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Install OVH DNS plugin

sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-ovh

2. Create OVH API Token

Where

Create the token at:

https://api.ovh.com/createToken/

Token settings

Validity: Unlimited

Required permissions (exact)

GET    /domain/zone
GET    /domain/zone/
GET    /domain/zone/qool.ovh
GET    /domain/zone/qool.ovh/*
POST   /domain/zone/qool.ovh/*
PUT    /domain/zone/qool.ovh/*
DELETE /domain/zone/qool.ovh/*

Note: OVH treats /domain/zone and /domain/zone/ as different paths. Certbot (Lexicon) requires the trailing slash permission.

wise.ovh, these are the API settings

GET    /domain/zone/
GET    /domain/zone/*
POST   /domain/zone/*
PUT    /domain/zone/*
DELETE /domain/zone/*

When API key is set, this can be executed:

sudo certbot certonly \
  --dns-ovh \
  --dns-ovh-credentials ~/.secrets/certbot/ovh.ini \
  -d wise.ovh -d '*.wise.ovh'

3. Store OVH Credentials Securely

Create credentials file

sudo nano /etc/letsencrypt/ovh.ini

File contents

dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = YOUR_APPLICATION_KEY
dns_ovh_application_secret = YOUR_APPLICATION_SECRET
dns_ovh_consumer_key = YOUR_CONSUMER_KEY

Lock down permissions

sudo chmod 600 /etc/letsencrypt/ovh.ini

4. Verify OVH API Access (Before Certbot)

Create a small Python test

import ovh

client = ovh.Client(
    endpoint='ovh-eu',
    application_key='YOUR_APPLICATION_KEY',
    application_secret='YOUR_APPLICATION_SECRET',
    consumer_key='YOUR_CONSUMER_KEY'
)

print(client.get('/domain/zone'))

Expected output

A list of domains including qool.ovh. If this works, the API token and permissions are correct.

5. Request the Wildcard Certificate

Run Certbot

sudo certbot certonly \
  --dns-ovh \
  --dns-ovh-credentials /etc/letsencrypt/ovh.ini \
  --dns-ovh-propagation-seconds 120 \
  --agree-tos \
  --email admin@qool.ovh \
  -d "*.qool.ovh" \
  -d "qool.ovh"

Successful result

Certbot reports that the certificate was issued and stored in:

/etc/letsencrypt/live/qool.ovh/

6. Verify and Test Renewal

Check certificate files

sudo ls -l /etc/letsencrypt/live/qool.ovh/

Test auto-renewal

sudo certbot renew --dry-run

Snap installs a systemd timer automatically, so renewals run without manual action.

7. Cleanup (Recommended)

Remove duplicate credential copies

Keep only:

/etc/letsencrypt/ovh.ini

Remove test artifacts

rm -f ~/python/set-ovy.py
rm -rf ~/ovh-test

Final Notes

Setup webserver (NGINX) on Ubuntu

Nginx + PHP + MariaDB + phpMyAdmin + SSH

0. Introduction

Goal

Set up a production-ready Ubuntu server with: Nginx, PHP (PHP-FPM), MariaDB, phpMyAdmin, and SSH on a custom port.

Assumptions


1. Secure SSH (Custom Port)

Edit SSH configuration

sudo nano /etc/ssh/sshd_config

Required settings

Port 1611
PermitRootLogin no
PasswordAuthentication yes

Apply changes

sudo ufw allow 1611/tcp
sudo systemctl restart ssh

Verify

sudo ss -tlnp | grep ssh

2. Install Nginx

Install

sudo apt update
sudo apt install nginx -y

Enable and start

sudo systemctl enable nginx
sudo systemctl start nginx

Allow firewall

sudo ufw allow 'Nginx Full'

3. Install PHP (PHP-FPM)

Install PHP and extensions

sudo apt install php-fpm php-cli php-mysql php-curl php-gd php-mbstring php-xml php-zip -y

Verify PHP

php -v
systemctl status php8.3-fpm

4. Configure Nginx + PHP

Default site config

sudo nano /etc/nginx/sites-available/default

Minimal PHP configuration

server {
    listen 80;
    server_name _;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Reload

sudo nginx -t
sudo systemctl reload nginx

5. Install MariaDB

Install

sudo apt install mariadb-server mariadb-client -y

Secure

sudo mysql_secure_installation

Create admin user

sudo mariadb
CREATE USER 'max'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO 'max'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

6. Install phpMyAdmin

Install package

sudo apt install phpmyadmin -y

When prompted:

 

Nginx configuration

sudo nano /etc/nginx/snippets/phpmyadmin.conf
location /phpmyadmin {
    root /usr/share/;
    index index.php;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Enable

sudo nano /etc/nginx/sites-available/default

Add:

include snippets/phpmyadmin.conf;
sudo nginx -t
sudo systemctl reload nginx

7. File Ownership & Permissions

Recommended structure

/var/www/qool/test

Ownership

sudo chown -R max:www-data /var/www/qool/test

Permissions

find /var/www/qool/test -type d -exec chmod 750 {} \;
find /var/www/qool/test -type f -exec chmod 640 {} \;

Final Notes

Set up subdomain routing NGINX

Dynamic Subdomain Routing for *.qool.ovh (Nginx)

0. Introduction

Goal

Automatically route requests for <subdomain>.qool.ovh to the corresponding directory /var/www/qool/<subdomain>, without creating a new DNS record or Nginx config for each site.

Use case


1. DNS Configuration (Wildcard)

Create wildcard DNS record

At your DNS provider (OVH), create the following record:

Type: A
Name: *.qool.ovh
Value: <SERVER_IP>
TTL: Auto

This ensures that all subdomains of qool.ovh resolve to your server.


2. Directory Structure

Base webroot layout

/var/www/qool/
 ├─ test/
 │   └─ index.php
 ├─ blog/
 │   └─ index.php
 └─ demo/
     └─ index.php

Ownership and permissions

sudo chown -R max:www-data /var/www/qool
find /var/www/qool -type d -exec chmod 750 {} \;
find /var/www/qool -type f -exec chmod 640 {} \;

3. Nginx Wildcard Configuration

Create Nginx site file

sudo nano /etc/nginx/sites-available/qool.ovh

Wildcard server block

server {
    listen 80;

    # Capture subdomain name dynamically
    server_name ~^(?<site>[a-z0-9-]+)\.qool\.ovh$;

    root /var/www/qool/$site;
    index index.php index.html;

    # Reject non-existing site directories
    if (!-d /var/www/qool/$site) {
        return 404;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Enable the site

sudo ln -s /etc/nginx/sites-available/qool.ovh /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

4. How the Routing Works

Nginx logic

Example

Request:

GET http://test.qool.ovh

Results in:

root = /var/www/qool/test

5. Testing

Create a test file

nano /var/www/qool/test/index.php
<?php
echo "Site: test.qool.ovh";

Test locally

curl -H "Host: test.qool.ovh" http://localhost

Test in browser

Open:

http://test.qool.ovh

6. Notes & Best Practices

Final Summary

Enable https NGINX

Enable HTTPS on Nginx (Let’s Encrypt)

0. Introduction

Goal

Enable HTTPS on Nginx using an existing Let’s Encrypt certificate, open the HTTPS port, and (optionally) redirect all HTTP traffic to HTTPS.


1. Prerequisites

Required files:

/etc/letsencrypt/live/qool.ovh/fullchain.pem
/etc/letsencrypt/live/qool.ovh/privkey.pem

2. Allow HTTPS Port (443)

Add firewall rule

sudo ufw allow 443/tcp

Enable firewall (if not active)

sudo ufw enable

Verify

sudo ufw status

3. Configure Nginx for HTTPS

Edit Nginx site configuration

sudo nano /etc/nginx/sites-available/qool.ovh

HTTPS server block

server {
    listen 443 ssl http2;
    server_name *.qool.ovh;

    root /var/www/qool;
    index index.php index.html;

    ssl_certificate     /etc/letsencrypt/live/qool.ovh/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/qool.ovh/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

4. Redirect HTTP to HTTPS (Recommended)

HTTP redirect block

server {
    listen 80;
    server_name *.qool.ovh;
    return 301 https://$host$request_uri;
}

5. Apply Configuration

Test configuration

sudo nginx -t

Reload Nginx

sudo systemctl reload nginx

6. Verify HTTPS

Check listening ports

sudo ss -tlnp | grep 443

Test in browser

https://test.qool.ovh

Test via CLI

curl -I https://test.qool.ovh

Final Notes